Non-negative Integers without Consecutive Ones
Introduction
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. 1
2
3
4
5
6
7
8
9
10
11
12Example 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.
Solution
A naive solution to check all numbers smaller or equal to n won’t work as it will give you TLE (Time Limit Exceeded) error on leetcode Online Judgement. Here I use dynamic programming method to recursively search solutions.
First of all, Compute cache[] like Fibonacci sequence, cache[i] means the number of Non-consecutive integers without consecutive ones for all integers of length i in its binary form. For example, cache[1] = 2 for both 0 and 1, cache[2] = 3 for 00, 01 and 10, cache[3] = 5 for 000, 001, 010, 100 and 101, so cache[i] = cache[i-1] + cache[i-2], because if the most significant digit of number in length i is 0, then the remaining i-1 digits have cache[i-1] Non-consecutive integers without consecutive ones. If it is 1, then the second most significant digit must be 0 to avoid consecutive ones, thus the remaining i-2 digits have cache[i-2] Non-consecutive integers without consecutive ones. Before we solve the problem, cache[] array can be pre-computated for future use and save some time.
Secondly, I came up with a equation to recursively find the solution. Given a number num, we define a function find(num) that equals to the number of Non-consecutive integers without consecutive ones, which are either smaller or equal to num. d[r] is used to denote the digit in position r. For a number in binary format like 11001, d[3] = 1, d[2] = 0, etc. We also define a new function rm2() to remove first two digits in binary form like from 110100 to 000100 by using mask to calculate 110100 & 001111.
$$ find(num)= \cases{ find(rm2(num)) + cache[r], & \text{if second most significant digit is 0.} \cr cache[r-1] + cache[r], & \text{otherwise} } $$
For example num = 11011, Use bit shift operation to find the position of most significant digit is r = 4, which is the same as the length of remaining digits without most significant digit. One part of the sum is the number of Non-consecutive integers without consecutive ones, which are less than num and d[r] = 0, is equal to cache[r]. The other part is the sum for cases when d[r] = 1, then the next digit of all integers must be 0 and there are two different conditions to consider: * For number num d[r-1] = 0, add find(rm2(num)) as we try to find all Non-consecutive integers without consecutive ones between 10000 and 10011, which is exactly equal to find(rm2(num)). * For number num d[r-1] = 1, add cache[r-1] as we try to find all Non-consecutive integers without consecutive ones between 10000 and 10111.
1 | public class NonNegativeIntegersWithoutConsecutiveOnes { |