600. 不含连续1的非负整数

方法一:递归

自然数 n 转换为二进制数字,如:600. 不含连续1的非负整数_递归600. 不含连续1的非负整数_递归_02
所有 600. 不含连续1的非负整数_二进制数字_03的数,考虑第二位,要么是1,要么是0。

对于 m:第二位是 0

前两位取 10 递归 $6 = (110)_2$,即除去前两位后的剩余二进制位;
第一位取 0 递归 $15 = (1111)_2$

对于 n:第二位是 1

前两位是 11 递归 $7 = (111)_2$,即除去前两位后的最大值,因为第二位只能取 0; 
第一位取 0 递归 $15 = (1111)_2$
class Solution:
    @lru_cache(None)
    def findIntegers(self, n: int) -> int:
        if n <= 3:
            return n + 1 if n < 3 else n
        bits = len(bin(n)) - 2
        return self.findIntegers((1<<(bits-1))-1) + (self.findIntegers((1<<(bits-2))-1) if (n >> (bits - 2)) & 1 else self.findIntegers(n - (1<<(bits-1))))
        # bin((1<<(5-1))-1) = '0b1111'

方法二:

class Solution:
    def findIntegers(self, n: int) -> int:
        dp = [0] * 32
        dp[0] = 1
        dp[1] = 2
        dp[2] = 3
        
        for i in range(3, 32):
            dp[i] = dp[i - 1] + dp[i - 2]        
        
        numStr = str(bin(n))[2:]
        m = len(numStr)
        
        res = 0
        for i in range(m):
            if numStr[i] != '0': 
                res += dp[m - i - 1]
                if i != 0 and numStr[i - 1] == '1':
                    return res
        
        return res + 1