LeetCodee

600. Non-negative Integers without Consecutive Ones

Problem 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 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 <= 109

Solution

Python Solution

class Solution:
    def findIntegers(self, n: int) -> int:
        # Get binary representation
        binary = bin(n)[2:]
        k = len(binary)
        
        # dp[i][j] represents the number of valid integers with length i
        # and ending with digit j
        dp = [[0, 0] for _ in range(k + 1)]
        dp[1] = [1, 1]
        
        # Fill dp table
        for i in range(2, k + 1):
            dp[i][0] = dp[i-1][0] + dp[i-1][1]  # can append 0 to both endings
            dp[i][1] = dp[i-1][0]  # can only append 1 to 0 ending
        
        # Count numbers less than n
        result = 0
        prev_bit = 0
        
        for i in range(k):
            if binary[i] == '1':
                result += dp[k-i][0]  # count numbers with 0 at this position
                if prev_bit == 1:  # consecutive ones found
                    return result
                prev_bit = 1
            else:
                prev_bit = 0
                
        return result + 1  # add 1 to include n itself

Time Complexity: O(log n)

Where log n is the length of the binary representation of n.

Space Complexity: O(log n)

For storing the dp table.

Java Solution

class Solution {
    public int findIntegers(int n) {
        // Get binary length
        int k = 32 - Integer.numberOfLeadingZeros(n);
        
        // dp[i][j] represents the number of valid integers with length i
        // and ending with digit j
        int[][] dp = new int[k + 1][2];
        dp[1][0] = dp[1][1] = 1;
        
        // Fill dp table
        for (int i = 2; i <= k; i++) {
            dp[i][0] = dp[i-1][0] + dp[i-1][1];  // can append 0 to both endings
            dp[i][1] = dp[i-1][0];  // can only append 1 to 0 ending
        }
        
        // Count numbers less than n
        int result = 0;
        int prevBit = 0;
        
        for (int i = k - 1; i >= 0; i--) {
            int bit = (n >> i) & 1;
            if (bit == 1) {
                result += dp[i + 1][0];  // count numbers with 0 at this position
                if (prevBit == 1) {  // consecutive ones found
                    return result;
                }
                prevBit = 1;
            } else {
                prevBit = 0;
            }
        }
        
        return result + 1;  // add 1 to include n itself
    }
}

Time Complexity: O(log n)

Where log n is the length of the binary representation of n.

Space Complexity: O(log n)

For storing the dp table.

C++ Solution

class Solution {
public:
    int findIntegers(int n) {
        // Get binary length
        int k = 32 - __builtin_clz(n);
        
        // dp[i][j] represents the number of valid integers with length i
        // and ending with digit j
        vector> dp(k + 1, vector(2));
        dp[1][0] = dp[1][1] = 1;
        
        // Fill dp table
        for (int i = 2; i <= k; i++) {
            dp[i][0] = dp[i-1][0] + dp[i-1][1];  // can append 0 to both endings
            dp[i][1] = dp[i-1][0];  // can only append 1 to 0 ending
        }
        
        // Count numbers less than n
        int result = 0;
        int prevBit = 0;
        
        for (int i = k - 1; i >= 0; i--) {
            int bit = (n >> i) & 1;
            if (bit == 1) {
                result += dp[i + 1][0];  // count numbers with 0 at this position
                if (prevBit == 1) {  // consecutive ones found
                    return result;
                }
                prevBit = 1;
            } else {
                prevBit = 0;
            }
        }
        
        return result + 1;  // add 1 to include n itself
    }
};

Time Complexity: O(log n)

Where log n is the length of the binary representation of n.

Space Complexity: O(log n)

For storing the dp table.

JavaScript Solution

/**
 * @param {number} n
 * @return {number}
 */
var findIntegers = function(n) {
    // Get binary length
    const binary = n.toString(2);
    const k = binary.length;
    
    // dp[i][j] represents the number of valid integers with length i
    // and ending with digit j
    const dp = Array(k + 1).fill().map(() => [0, 0]);
    dp[1][0] = dp[1][1] = 1;
    
    // Fill dp table
    for (let i = 2; i <= k; i++) {
        dp[i][0] = dp[i-1][0] + dp[i-1][1];  // can append 0 to both endings
        dp[i][1] = dp[i-1][0];  // can only append 1 to 0 ending
    }
    
    // Count numbers less than n
    let result = 0;
    let prevBit = 0;
    
    for (let i = 0; i < k; i++) {
        if (binary[i] === '1') {
            result += dp[k-i][0];  // count numbers with 0 at this position
            if (prevBit === 1) {  // consecutive ones found
                return result;
            }
            prevBit = 1;
        } else {
            prevBit = 0;
        }
    }
    
    return result + 1;  // add 1 to include n itself
};

Time Complexity: O(log n)

Where log n is the length of the binary representation of n.

Space Complexity: O(log n)

For storing the dp table.

C# Solution

public class Solution {
    public int FindIntegers(int n) {
        // Get binary length
        int k = 32 - BitOperations.LeadingZeroCount((uint)n);
        
        // dp[i][j] represents the number of valid integers with length i
        // and ending with digit j
        int[,] dp = new int[k + 1, 2];
        dp[1, 0] = dp[1, 1] = 1;
        
        // Fill dp table
        for (int i = 2; i <= k; i++) {
            dp[i, 0] = dp[i-1, 0] + dp[i-1, 1];  // can append 0 to both endings
            dp[i, 1] = dp[i-1, 0];  // can only append 1 to 0 ending
        }
        
        // Count numbers less than n
        int result = 0;
        int prevBit = 0;
        
        for (int i = k - 1; i >= 0; i--) {
            int bit = (n >> i) & 1;
            if (bit == 1) {
                result += dp[i + 1, 0];  // count numbers with 0 at this position
                if (prevBit == 1) {  // consecutive ones found
                    return result;
                }
                prevBit = 1;
            } else {
                prevBit = 0;
            }
        }
        
        return result + 1;  // add 1 to include n itself
    }
}

Time Complexity: O(log n)

Where log n is the length of the binary representation of n.

Space Complexity: O(log n)

For storing the dp table.

Approach Explanation

The solution uses dynamic programming with bit manipulation:

  1. Key Insights:
    • Binary representation
    • Dynamic programming
    • State transitions
    • Bit manipulation
  2. Algorithm Steps:
    • Get binary length
    • Build dp table
    • Process bits
    • Handle edge cases

Implementation Details:

  • DP state definition
  • Transition rules
  • Bit counting
  • Result accumulation

Optimization Insights:

  • Early termination
  • Space optimization
  • Bit operations
  • State compression

Edge Cases:

  • Small numbers
  • Power of two
  • Maximum value
  • Single bit