找出没有相邻的1的二进制数的个数---2013年2月17日
生活随笔
收集整理的這篇文章主要介紹了
找出没有相邻的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的二进制数的个数---2013年2月17日的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入Oracle的left join中o
- 下一篇: jQuery知识简介