解题代码:
classSolution {
public:
int findIntegers(int num) {
if(num==0)
return 1;
if(num==1)
return 2;
if(num<=3)
return 3;
int i=2,j=0;
while(num>=i){
i*=2;
j++;
}
if(num>=3*i/4){
int a=2,b=3,s=1;
while(s<j){
int t=a+b;
a=b;
b=t;
s++;
}
return b;
}
else{
int a=2,b=3,s=1;
while(s<j-1){
int t=a+b;
a=b;
b=t;
s++;
}
return b+findIntegers(num-i/2);
}
}
};
解题思路:
根据本题的要求,给出一个整数num,要求返回在小于等于num的非负整数中,二进制的形态下没有连续的1的数的个数。首先我们观察规律,可以发现如下的特性:
1.对于[2i, 2i+1)区间而言,里面数字的个数共有2i个,把它们分成两半,后面的2i-1个数字必然都是有相连的1的,而对于前2i-1个数字,它们是否存在连续1的情况分别与[0,2i-1)一一对应,也即是相同。
2.若要求小于2i的数中二进制中没有连续1的数的个数,可以设为a[i]。我们可以观察规律,若i=1,有a[i]=2,若i=2,a[i]=3,若i=3,a[i]=5……对于更普遍的情况,a[i]= a[i-1]+a[i-2]
根据上述的特性,我们可以完成题目的要求:首先我们分析num属于哪个区间,也即是找到[2i, 2i+1)使得num在这个区间里面。然后我们再研究,若num在这个区间的后2i-1个数字中,我们可以直接认为,答案就等于小于2i+1的数中二进制中没有连续1的数的个数。
而若num在区间的前2i-1个数字中,我们可以把需要求的分解成求小于2i的数中二进制中没有连续1的数的个数加上2i到num的数中二进制中没有连续1的数的个数。而上面后者其实相当于就是求小于等于num-2i的数中二进制中没有连续1的数的个数。