LeetCode #600 Non-negative Integers without Consecutive Ones 不含连续1的非负整数

600 Non-negative Integers without Consecutive Ones 不含连续1的非负整数

Description:
Given a positive integer n, return the number of the integers in the range [0, n] whose binary representations do not contain consecutive ones.

Example:

Example 1:

Input: n = 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.

Example 2:

Input: n = 1
Output: 2

Example 3:

Input: n = 2
Output: 3

Constraints:

1 <= n <= 10^9

题目描述:

给定一个正整数 n,找出小于或等于 n 的非负整数中,其二进制表示不包含 连续的1 的个数。

示例 :

示例 1:

输入: 5
输出: 5
解释:
下面是带有相应二进制表示的非负整数<= 5:

0 : 0
1 : 1
2 : 10
3 : 11
4 : 100
5 : 101

其中,只有整数3违反规则(有两个连续的1),其他5个满足规则。

说明:
1 <= n <= 10^9

思路:

动态规划
dp[i] 表示 i 位二进制中有 dp[i] 个不含连续 1 的二进制数
比如 dp[2] = 2, 表示 10 和 01 这两个二进制数满足不含连续 1
动态转移方程 dp[i] = dp[i - 1] + dp[i - 2], 因为对第 i 位, 可由 i - 1 位在高位加 0 得到, 也可以由 i - 2 位在高位加 10 得到
现在求 n = 11, 即 n = 1011
每次用一个 mask 取当前位
对前 1 位 1
mask = 1, n & mask > 0, n & (mask >> 1) == 0, result = dp[1], result = 1
对前 2 位 11
mask = 2, n & mask > 0, n & (mask >> 1) > 0, result = dp[2], result = 3
对前 4 位 1011
mask = 8, n & mask = 1, n & (mask >> 1) = 0, result += dp[4], result = 8
然后就可以跳出循环
这样就判断完了 1-10 中的所有数字, 还剩下 11 没有判断
因为如果有连续的 1 时, n & (n - 1) > 0, 最后处理一下就可以了
时间复杂度 O(1), 空间复杂度 O(1), 最多需要 64 次循环, 需要一个长度为 32 的辅助数组

代码:
C++:

class Solution 
{
public:
    int findIntegers(int n) 
    {
        vector<int> dp(32);
        dp[0] = 1;
        dp[1] = 2;
        for (int i = 2; i < 32; i++) dp[i] = dp[i - 1] + dp[i - 2];
        int result = !(n & (n >> 1));
        for (int i = 1, mask = 1; mask <= n and i < 32; i++, mask <<= 1)
        {
            if (mask & n)
            {
                if ((mask >> 1) & n) result = dp[i];
                else result += dp[i - 1];
            }
        }
        return result;
    }
};

Java:

class Solution {
    public int findIntegers(int n) {
        int dp[] = new int[32], result = ((n & (n >> 1)) > 0) ? 0 : 1;
        dp[0] = 1;
        dp[1] = 2;
        for (int i = 2; i < 32; i++) dp[i] = dp[i - 1] + dp[i - 2];
        for (int i = 1, mask = 1; mask <= n && i < 32; i++, mask <<= 1) {
            if ((mask & n) > 0) {
                if (((mask >> 1) & n) > 0) result = dp[i];
                else result += dp[i - 1];
            }
        }
        return result;
    }
}

Python:

class Solution:
    def findIntegers(self, n: int) -> int:
        dp, result, mask = [1, 2] + [0] * 30, not (n >> 1 & n), 1
        for i in range(2, 32):
            dp[i] = dp[i - 1] + dp[i - 2]
        for i in range(1, 32):
            if mask > n:
                break
            if (mask & n):
                if ((mask >> 1) & n):
                    result = dp[i]
                else:
                    result += dp[i - 1]
            mask <<= 1
        return result
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容