Description:
Given a positive integer n, find the number of non-negative integers less than or equal to n, whose binary representations do NOT contain consecutive ones.
Example:
Input: 5
Output: 5
Explanation:
Here are the non-negative integers <= 5 with their corresponding binary representations:
0 : 0
1 : 1
2 : 10
3 : 11
4 : 100
5 : 101
Among them, only integer 3 disobeys the rule (two consecutive ones) and the other 5 satisfy the rule.
Link:
https://leetcode.com/problems/non-negative-integers-without-consecutive-ones/description/
解题方法:
- 第一步:
首先算出num是几位的二进制。
用两个array来做DP的辅助数组:
DP0[i]代表在第i位上取0的符合规则的数的个数。
DP1[i]代表在第i位上取1的符合规则的数的个数。
状态转移方程:
DP1[i] = DP0[i - 1];
DP0[i] = DP1[i - 1] + DP0[i - 1];
- 第二部:
然后从高位往低位遍历num,需要求出小于num的所有符合规则的数的个数。
当num的第i位为1的情况,
result += DP0[i];
当第i位为0的情况,直接跳过。
当有两位连续的1出现,算完第二个1的位置上为0的个数以后,跳出循环,因为之后所有的符合个数的数都已经算过了,比如说:
num = 1 0 1 1 ...
假设第一个连续1的位置是 i,第二个为 i+1;
当我们读到 i 时:
result += DP0[i]
其实就是统计了所有1 0 0 ....
的个数
当我们读到 i + 1的时候:
result += DP0[i - 1]
这样就统计了所有1 0 1 0 ....
的个数
也就是说不管后面有什么0 或者 1,都被统计了。
最后别忘记算上num这个数,如果它也符合规则。
Time Complexity:
O(lgn)
完整代码:
int findIntegers(int num) {
if(!num)
return 0;
int cnt = 0;
while(1 << cnt <= num) {
++cnt;
}
vector<int> DP0(cnt + 1, 0);
vector<int> DP1(cnt + 1, 0);
DP0[1] = 1;
DP1[1] = 1;
for(int i = 2; i <= cnt; i++) {
DP0[i] = DP0[i - 1] + DP1[i - 1];
DP1[i] = DP0[i - 1];
}
bool last = false;
bool obRule = true;
int result = 0;
while(--cnt >= 0) {
//curr postion is 1
if(1 << cnt & num) {
result += DP0[cnt + 1];
if(last) {
obRule = false;
break;
}
last = true;
}
//curr position is 0
else
last = false;
}
if(obRule)
result += 1;
return result;
}
网友评论