Count of non-consecutive Ones in Binary range
Last Updated : 14 Oct, 2023
Given two positive integers 'L' and 'R', the task is to return the number of the integers in the range [L, R] inclusive, whose binary representations do not contain consecutive ones where 0 ≤ l ≤ r ≤ 10^9
Examples:
Input: L = 0, R = 3
Output: 3
Explanation: The 3 numbers are 0(00), 1(01), 2(10) 3(11) is not included as its binary representation contains consecutive ones
Input: L = 5, R = 10
Output: 4
Explanation: The 4 numbers are 5(101), 8(1000), 9(1001), 10(1010)
If we say G(x) tells the number of such integers between 0 to x (inclusively) without consecutive 1's in their binary representation, then the number of such integers between L and R can be given by G(R) – G(L-1). This is when Digit DP (Dynamic Programming) comes into action. All such integer counting problems that satisfy the above property can be solved by the digit DP approach.
Intuition:
If we use the Digit DP approach to build all the binary String from the [ 0, R ] range and [0, L-1] range. then return Numbers in [0, R] range - Numbers in [0, L-1] range. So, we have only 2 digits to form the binary number i.e. 1 and 0.
Steps to solve the above approach:
- The algorithm iterates through each digit position of the binary representation of 10^9 i.e. it's 32-bit long.
- It keeps track of the previous digit, whether it's 0, 1, or an initial state
- It considers a "tight" flag that determines the upper bound of the current digit based on the previous digits and the given range.
- It recursively calculates the count of valid integers by considering all possible digits at each position, excluding combinations with consecutive 1s.
- The algorithm sums up the counts from all recursive calls and memoizes the result for future use.
- Finally, the algorithm returns the count of valid integers within the given range by subtracting the count of valid integers from the [L, R] range inclusively.
Below is the implementation of the above approach:
C++ // Cpp code for the above approach: #include <iostream> #include <cstring> #include <bitset> using namespace std; // Function to solve the digit DP problem long long solve(string str, int idx, int prev, int tight, long long dp[33][3][2]); // Function to compute the count of non-negative integers // with no consecutive ones in their binary representation long long digitDP(string str) { long long dp[33][3][2]; // 3D dynamic programming array memset(dp, -1, sizeof(dp)); // Initialize all elements to -1 return solve(str, 0, 2, 1, dp); // Solve the problem using dynamic programming } // Recursive function to solve the digit DP problem long long solve(string str, int idx, int prev, int tight, long long dp[33][3][2]) { // Base case: If we have reached the end of the string, return 1 if (idx >= str.length()) { return 1LL; } // If the result for the current state is already computed, return it if (dp[idx][prev][tight] != -1) { return dp[idx][prev][tight]; } long long ans = 0; int upperBound = (tight == 1 ? str[idx] - '0' : 1); // Determine the upper bound for the current digit based on the "tight" flag // Iterate through all possible digits from 0 to the upper bound for (int dgt = 0; dgt <= upperBound; dgt++) { int newTight = (tight == 0 ? 0 : (dgt == upperBound ? 1 : 0)); // Determine the new "tight" flag based on the current digit and the upper bound // If the previous digit and the current digit are both 1, skip this combination if (prev == 1 && dgt == 1) { continue; } // Recursively solve for the next digit ans += solve(str, idx + 1, dgt, newTight, dp); } // Memoize the result and return it return dp[idx][prev][tight] = ans; } // Function to compute the count of non-negative integers // with no consecutive ones in their binary representation long long findIntegers(int l, int r) { if (l == 0) { return digitDP(bitset<32>(r).to_string()); } l--; return digitDP(bitset<32>(r).to_string()) - digitDP(bitset<32>(l).to_string()); } // Driver code int main() { // Example usage cout << findIntegers(0, 3) << endl; cout << findIntegers(5, 10) << endl; cout << findIntegers(10, 1000000000) << endl; return 0; }
Java // Java code for the above approach: import java.util.*; class GFG { public static long findIntegers(int l, int r) { // Convert the given integer to // its binary representation if (l == 0) { return digitDP(Integer.toBinaryString(r)); } l--; return digitDP(Integer.toBinaryString(r)) - digitDP(Integer.toBinaryString(l)); } public static long digitDP(String str) { // Create a 3D dynamic programming // array long[][][] dp = new long[33][3][2]; // Initialize all elements of // the array to -1 for (long[][] ar : dp) { for (long[] e : ar) { Arrays.fill(e, -1); } } // Solve the problem using // dynamic programming return solve(str, 0, 2, 1, dp); } public static long solve(String str, int idx, int prev, int tight, long[][][] dp) { // Base case: If we have reached // the end of the string, return 1 if (idx >= str.length()) { return 1L; } // If the result for the current // state is already computed, // return it if (dp[idx][prev][tight] != -1) { return dp[idx][prev][tight]; } long ans = 0; // Determine the upper bound for // the current digit based on // the "tight" flag int upperBound = (tight == 1 ? str.charAt(idx) - '0' : 1); // Iterate through all possible // digits from 0 to the upper bound for (int dgt = 0; dgt <= upperBound; dgt++) { // Determine the new "tight" // flag based on the current // digit and the upper bound int newTight = (tight == 0 ? 0 : (dgt == upperBound ? 1 : 0)); // If the previous digit and // the current digit are both 1, // skip this combination if (prev == 1 && dgt == 1) { continue; } // Recursively solve for // the next digit ans += solve(str, idx + 1, dgt, newTight, dp); } // Memoize the result and return it return dp[idx][prev][tight] = ans; } // Drivers code public static void main(String args[]) { System.out.println(findIntegers(0, 3)); System.out.println(findIntegers(5, 10)); System.out.println(findIntegers(10, 1000000000)); } }
Python3 # Python3 code to solve the above problem # Function to solve the digit DP problem def solve(str, idx, prev, tight, dp): # Base case: If we have reached the end of the string, return 1 if idx >= len(str): return 1 # If the result for the current state is already computed, return it if dp[idx][prev][tight] != -1: return dp[idx][prev][tight] ans = 0 upperBound = int(str[idx]) if tight == 1 else 1 # Determine the upper bound for the current digit based on the "tight" flag # Iterate through all possible digits from 0 to the upper bound for dgt in range(upperBound + 1): newTight = 0 if (tight == 0) else ( 1 if dgt == upperBound else 0 ) # Determine the new "tight" flag based on the current digit and the upper bound # If the previous digit and the current digit are both 1, skip this combination if prev == 1 and dgt == 1: continue # Recursively solve for the next digit ans += solve(str, idx + 1, dgt, newTight, dp) # Memoize the result and return it dp[idx][prev][tight] = ans return ans # Function to compute the count of non-negative integers # with no consecutive ones in their binary representation def findIntegers(l, r): if l == 0: return solve(bin(r)[2:], 0, 2, 1, [[[-1 for _ in range(2)] for _ in range(3)] for _ in range(32)]) l -= 1 return solve(bin(r)[2:], 0, 2, 1, [[[-1 for _ in range(2)] for _ in range(3)] for _ in range(32)]) - solve(bin(l)[2:], 0, 2, 1, [[[-1 for _ in range(2)] for _ in range(3)] for _ in range(32)]) # Example usage print(findIntegers(0, 3)) print(findIntegers(5, 10)) print(findIntegers(10, 1000000000)) # This code is contributed by Tapesh(tapeshdua420)
C# // C# code for the above approach using System; public class GFG { public static long FindIntegers(int l, int r) { // Convert the given integer to its binary // representation if (l == 0) { return DigitDP(Convert.ToString(r, 2)); } l--; return DigitDP(Convert.ToString(r, 2)) - DigitDP(Convert.ToString(l, 2)); } public static long DigitDP(string str) { // Create a 3D dynamic programming array long[, , ] dp = new long[33, 3, 2]; // Initialize all elements of the array to -1 for (int i = 0; i < 33; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 2; k++) { dp[i, j, k] = -1; } } } // Solve the problem using dynamic programming return Solve(str, 0, 2, 1, dp); } public static long Solve(string str, int idx, int prev, int tight, long[, , ] dp) { // Base case: If we have reached the end of the // string, return 1 if (idx >= str.Length) { return 1L; } // If the result for the current state is already // computed, return it if (dp[idx, prev, tight] != -1) { return dp[idx, prev, tight]; } long ans = 0; // Determine the upper bound for the current digit // based on the "tight" flag int upperBound = (tight == 1) ? (str[idx] - '0') : 1; // Iterate through all possible digits from 0 to the // upper bound for (int dgt = 0; dgt <= upperBound; dgt++) { // Determine the new "tight" flag based on the // current digit and the upper bound int newTight = (tight == 0) ? 0 : ((dgt == upperBound) ? 1 : 0); // If the previous digit and the current digit // are both 1, skip this combination if (prev == 1 && dgt == 1) { continue; } // Recursively solve for the next digit ans += Solve(str, idx + 1, dgt, newTight, dp); } // Memoize the result and return it dp[idx, prev, tight] = ans; return ans; } // Driver code public static void Main(string[] args) { Console.WriteLine(FindIntegers(0, 3)); Console.WriteLine(FindIntegers(5, 10)); Console.WriteLine(FindIntegers(10, 1000000000)); } } // This code is contributed by Susobhan Akhuli
JavaScript //JavaScript implementation of the above approach // Function to solve the digit DP problem function solve(str, idx, prev, tight, dp) { // Base case: If we have reached the end of the string, return 1 if (idx >= str.length) { return 1; } // If the result for the current state is already computed, return it if (dp[idx][prev][tight] !== -1) { return dp[idx][prev][tight]; } let ans = 0; let upperBound = tight === 1 ? parseInt(str[idx]) : 1; // Determine the upper bound for the current digit based on the "tight" flag // Iterate through all possible digits from 0 to the upper bound for (let dgt = 0; dgt <= upperBound; dgt++) { let newTight = tight === 0 ? 0 : (dgt === upperBound ? 1 : 0); // Determine the new "tight" flag based on the current digit and the upper bound // If the previous digit and the current digit are both 1, skip this combination if (prev === 1 && dgt === 1) { continue; } // Recursively solve for the next digit ans += solve(str, idx + 1, dgt, newTight, dp); } // Memoize the result and return it dp[idx][prev][tight] = ans; return ans; } // Function to compute the count of non-negative integers // with no consecutive ones in their binary representation function findIntegers(l, r) { if (l === 0) { return solve((r).toString(2), 0, 2, 1, Array.from({length: 32}, () => Array.from({length: 3}, () => Array.from({length: 2}, () => -1)))); } l -= 1; return solve((r).toString(2), 0, 2, 1, Array.from({length: 32}, () => Array.from({length: 3}, () => Array.from({length: 2}, () => -1)))) - solve((l).toString(2), 0, 2, 1, Array.from({length: 32}, () => Array.from({length: 3}, () => Array.from({length: 2}, () => -1)))); } // Example usage console.log(findIntegers(0, 3)); console.log(findIntegers(5, 10)); console.log(findIntegers(10, 1000000000)); // This code is contributed by Sakshi
Time Complexity: O(2*idx*prev*tight)
Auxiliary Space: O(idx * prev* tight)
Similar Reads
Count of groups of consecutive 1s in a given Binary String Given a binary string S of size N, the task is to find the number of groups of 1s only in the string S. Examples: Input: S = "100110111", N = 9Output: 3Explanation: The following groups are of 1s only: Group over the range [0, 0] which is equal to "1".Group over the range [3, 4] which is equal to "1
5 min read
Count number of binary strings without consecutive 1's Given a positive integer n, the task is to count all possible distinct binary strings of length n such that there are no consecutive 1's.Examples: Input: n = 3Output: 5Explanation: 5 strings are ("000", "001", "010", "100", "101").Input: n = 2Output: 3Explanation: 3 strings are ("00", "01", "10").Ta
15+ min read
Count numbers in range [L, R] having K consecutive set bits Given three positive integers l, r, and k, the task is to find the count of numbers in the range [l, r] having k consecutive set bits in their binary representation.Examples:Input: l = 4, r = 15, k = 3 Output: 3 Explanation: Numbers whose binary representation contains k=3 consecutive set bits are:
13 min read
Count number of binary strings without consecutive 1âs : Set 2 Given a positive integer N, the task is to count all possible distinct binary strings of length N such that there are no consecutive 1âs. Examples: Input: N = 5 Output: 5 Explanation: The non-negative integers <= 5 with their corresponding binary representations are: 0 : 0 1 : 1 2 : 10 3 : 11 4 :
15+ min read
Maximum consecutive oneâs (or zeros) in a binary array Given a binary array arr[] consisting of only 0s and 1s, find the length of the longest contiguous sequence of either 1s or 0s in the array.Examples : Input: arr[] = [0, 1, 0, 1, 1, 1, 1]Output: 4Explanation: The maximum number of consecutive 1âs in the array is 4 from index 3-6.Input: arr[] = [0, 0
7 min read