找出沒有相鄰的1的二進位制數的個數---2013年2月17日
問題描述:用G(n)表示在有n位的二進位制數中沒有相鄰的兩個1的二進位制數個數。比如,當n=3時,000,001,010,011,100,101,110,111這8個數中只有000,001,010,100,101這5個是沒有相鄰為1的,故G(3)=5。請寫一個程式,輸出G(n)的值。
錯誤的思路(考慮的不周全):採用"分治"的方法,比如n=3,每次都將處理原問題規模的二分之一,直到n=1時,就很容易可以知道有兩種情況。前面是"分",然後是"合"。比如把規模為n的問題分成了p1和p2部分,而且p1和p2問題都已經解決,個數已經知道。那麼,把p1和p2合起來的時候就只需要注意p1的最右邊和p2的最左邊的數不能同時為1,即:合起來的總的個數是:1*(p2-1)+(p1-1)*p2。"遞迴"和"分治"不分家,所以很容易寫出下面的程式。
以下是錯誤的程式碼。
錯誤的程式碼
1 int calculate(int n)
2 {
3 if(n==1)
4 return 2;
5 if(p[n]!=0)
6 return p[n];
7 int div=n/2;
8 return (p[n]=calculate(n-div)-1 + (calculate(div)-1)*calculate(n-div));
9 }
正確的思路:演算法的核心思想不變,依然是"分治"。"分"的部分很好處理,"合"的時候就容易出錯了。我之前就是在合併的時候沒有考慮周全。依然是把規模為n的問題分成p1和p2部分,令div=n/2,那麼p1中有div個元素,p2中有n-div個元素。合併的時候,已經保證p1,p2部分分別都沒有相鄰的兩個1了,這時需要注意的就只是p1的最右邊一個數和p2的最左邊的一個數了。分兩種情況(要用到排列組合的基礎知識):
將p1中最右邊的數記為A,p2中最左邊的數記為B,方便下面的文字描述。
1.A不為1。這種情況比下一種情況簡單一些。在p1中,A不為1,那麼A就是0了。這種情況下,G(div)=G(div-1)。再來考慮p2。既然A為0,那麼B即使為1也沒關係了。所以,這種情況下的結果就是G(div-1)*G(n-div)。
2.A為1。因為A為1,那麼A左邊的第一個數必然為0(因為p1中沒有兩個相鄰的1),所以在這種情況下G(div)=G(div-2)。再來考慮p2。既然A為1,那麼B肯定得為0了,那麼B右邊的數也就沒有限制了,即G(n-div-1)。所以,這種情況下的結果就是G(div-2)*G(n-div-1)。
程式碼如下:
1 #include <stdio.h>
2 #define MAX 1000
3
4 int p[MAX]={0};
5
6 //prototype
7 int calculate(int n);
8
9 int main()
10 {
11 int n=6;
12 int result=calculate(n);
13 printf("%d\n",result);
14 return 0;
15 }
16
17 int calculate(int n)
18 {
19 if(n<1)
20 return 1;
21 if(n==1)
22 return 2;
23 if(p[n]!=0)
24 return p[n];
25 int div=n/2;
26 return (p[n]=(calculate(div-2) * (calculate(n-div-1)) + calculate(div-1)*calculate(n-div)));
27 }
通過程式,可以得到G(1)=2,G(2)=3,G(3)=5,G(4)=8,G(5)=13,G(6)=21......可以看出這是一個斐波拉契數列。
本文轉自NeilHappy 51CTO部落格,原文連結:http://blog.51cto.com/neilhappy/1134394,如需轉載請自行聯絡原作者
相關文章
- 二進位制中1的個數
- 求一個整數的二進位制中1的個數
- 位運算--求一個 數二進位制中1的個數
- 位運算(一):二進位制中1的個數
- 【劍指offer】二進位制中1的個數
- 【c語言】統計一個數二進位制中的1的個數C語言
- 求一個數的二進位制數中所含1的個數的程式碼實現
- 【刷演算法】二進位制中1的個數演算法
- 題目1513:二進位制中1的個數
- 求二進位制數中1的個數(程式設計之美)程式設計
- 劍指 Offer 15. 二進位制中1的個數
- JZ-011-二進位制中 1 的個數
- 負數的二進位制數問題
- 根據數字二進位制下 1 的數目排序排序
- 查詢數N二進位制中1的個數(JS版 和 Java版)JSJava
- poj3252 數位dp(所有比n小的二進位制位0的個數不少於1的個數)記憶化搜尋
- 1417 二進位制數的大小
- 【劍指offer中等部分4】二進位制中1的個數(java)Java
- offer通過--10二進位制中統計1的個數-2
- 力扣 根據數字二進位制下1的數目排序力扣排序
- mysql二進位制日誌相關引數MySql
- 用c語言實現輸入一個十進位制數,計算其轉換為二進位制數後其中包含1的個數C語言
- 有趣的二進位制3—浮點數
- 二進位制求5個1的格式。。。。
- C++輸入十進位制數,輸出對應二進位制數、十六進位制數C++
- 用C#實現二進位制的減法(包括二進位制小數)C#
- 【c語言】將一個數的二進位制序列逆序,然後輸出逆序之後的二進位制序,所對應的數C語言
- 不知jdon有沒有研究過二進位制class檔案的
- 02_Python學習筆記之統計整數二進位制中1的個數Python筆記
- 負數補碼(16進位制轉10進位制的負數)
- 數的進位制轉換
- 5 個找出“二進位制命令”描述和系統中位置的方法
- 力扣1356.根據數字二進位制下1的數目排序力扣排序
- 演算法學習記錄九(C++)--->二進位制中1的個數演算法C++
- 知多一點二進位制中的負數
- mysql二進位制日誌的引數介紹MySql
- 如何把十進位制的數輸入用二進位制全加器,並以十進位制輸出
- JavaScript 二進位制數字轉換為十進位制JavaScript