LC-600 Non-negative Integers without Consecutive Ones

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 1:

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. 

Note: 1 <= n <= 109

Solution:

# brute force 解法
# O(n)
class Solution(object):
    def findIntegers(self, num):
        count = 0
        for i in range(0, num + 1):
            if self.isValid(i):
                count += 1
        return count

    def isValid(self, num):
        # get binary representation of num
        s = bin(num)[2:]    # bin(3) -> '0b11'; bin(3)[2:] -> '11'
        for i in range(0, len(s) - 1):
            if s[i] == '1' and s[i + 1] == '1':
                return False

        return True

# 最优解
class Solution(object):
    def findIntegers(self, num):
        """
        :type num: int
        :rtype: int
        """
        # num_bin[0] represent the higest effective bit
        # !!! num_bin is start with 1
        num_bin = str(bin(num))[2:]
        n = len(num_bin)

        # a[i] means number of binary string with length i
        # which do not contains any concecutive ones and which end in 0
        a = [0] * (n + 1)
        b = [0] * (n + 1)
        a[1] = b[1] = 1
        for i in range(2, n + 1):
            a[i] = a[i - 1] + b[i - 1]
            b[i] = a[i - 1]

        res = a[n] + b[n]

        # 举个1000的例子
        # 第一次遇到00,删除101* -> b[2]
        # 第二次遇到00, 删除1001 -> b[1]
        
        # 从高位到低位遍历
        for i in range(n - 1):
            # if num is 11**, then all permutations is less that it
            # we could break the for loop
            if num_bin[i] == num_bin[i + 1] == '1':
                break

            # if we met 01, according to the dp formula, the number of qualified integers
            # for first 0 should be 00 and 01, both of them are less than or equal to 01. The same for 10.

            # if we met 10, according to the dp formula, the number of qualified integers
            # for first 1 should be 10, It equal to 10

            # for 00, the number of qualified integers for first 0 should be 00 and 01,
            #  but 01 is greater than 00, we should subtract it.

            # for i == 1
            # if num is 1001, we need to delete 101*
            # because 101*  == b[2]
            # b[n - (i + 1)] -> b[4 - (1 + 1)]
            if num_bin[i] == num_bin[i + 1] == '0':
                # i + 1 is ith from the highest effective bit
                # (i + 1) start from 1
                res -= b[n - (i + 1)]

        return res


res = Solution().findIntegers(3)
print(res)  # 3

res = Solution().findIntegers(9)
print(res)  # 7  只有0b1010比9大

你可能感兴趣的:(LC-600 Non-negative Integers without Consecutive Ones)