Skip to content
Related Articles

Related Articles

Improve Article
Count numbers in range [L, R] having K consecutive set bits
  • Last Updated : 03 Jun, 2021

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:
Explanation: 
Numbers whose binary representation contains K(=3) consecutive set bits are: 
(7)10 = (111)2 
(14)10 = (1110)2 
(15)10 = (1111)2 
Therefore, the required output is 3. 

Input: L = 8, R = 100, K = 3 
Output: 27

Naive Approach: The simplest approach to solve this problem to traverse all possible integers in the range [L, R] and for each number, check if binary representation of the number contains K consecutive 1s or not. If found to be true then print the number.



Time Complexity: O((R – L + 1) * 32)
Auxiliary Space: O(1)

Efficient Approach: The problem can be solved using Digit DP. The idea is to count of numbers having K consecutive 1s in the range [1, R] and subtract the count of the numbers having K consecutive 1s in the range [1, L – 1]. Following are the recurrence relations:

cntN1X(len, cntOne, KOne)                  [Tex]= \sum^{1}_{i=0} cntN1X(len + 1, cntOne + i, KOne | (cntOne == K))                 [/Tex]
 

cntN1X(len, cntOne, KOne): Stores the count of numbers in the range [1, X] with the following constraints: 
len = length of binary representation of X
cntOne = Count of consecutive 1s till index len
KOne = Boolean value to check if K consecutive 1s present in X or not. 
 

 

Follow the steps below to solve the problem:

  • Initialize a 4D array dp[len][cntOne][KOne][tight] to compute and store the values of all subproblems of the above recurrence relation.
  • Finally, return the value of dp[len][cntOne][KOne][tight].

Below is the implementation of the above approach:

C++




// C++ program to implement
// the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the count of numbers in
// range[1, X] having K consecutive set bits
int cntN1X(string str, int len, int K,
    int cntOne, int dp[32][32][2][2],
                bool KOne, bool tight)
{
    // If length of current number is
    // equal to length of string
    if (len == str.length()) {
         
        // If count of consecutive set bits
        // in the current string is >= K
        return (KOne == 1);
    }
     
    // If already computedx
    // equal occurred
    if (dp[len][cntOne][KOne][tight]
                                   != -1) {
        return dp[len][cntOne][KOne][tight];
    }
 
    // If tight is 1, then element present
    // at current index is element present
    // in str at current index. Otherwise, 1.
    int end = tight ? (str[len] - '0'): 1;
     
    // Stores count of numbers whose
    // len th bit is i.
    int res = 0;
     
    // Iterate over all possible
    // value present at current index.
    for(int i = 0; i <= end; i++) {
         
        // Stores count of consecutive 1s
        int temp = (i==1) ? (cntOne + 1): 0;
         
        // Update res.
        res += cntN1X(str, len + 1,
        K, temp, dp, (KOne | (temp == K)),
                    (tight & (i==end)));
    }
     
    return dp[len][cntOne][KOne][tight]
                                    = res;
}
 
 
// Function to find
// binary representation of N
string convertBinary(int N)
{
    // Stores binary
    // representation of N.
    string res;
     
    // Traverse each bit of N.
    while(N) {
         
        // Append current bit
        // in res
        res.push_back(N % 2 + '0');
         
        // Update N.
        N /= 2;
    }
     
    // Append 0 in binary representation
    // Of N
    while(res.length() < 32) {
        res.push_back('0');
    }
     
    // Reverse binary representation of N
    reverse(res.begin(), res.end());
     
    return res;
}
 
// Function to count numbers in
// range[L, R] having K consecutive 1s.
int cntN1XL_R(int L, int R, int K)
{
    // Stores binary representation
    // of (L - 1)
    string Ls = convertBinary(L - 1);
     
    // Stores binary representation
    // of R
    string Rs = convertBinary(R);
     
    // Stores values of overlapping
    // subproblems
    int dp[32][32][2][2];
     
    // Initialize dp[][][][] array.
    memset(dp, -1, sizeof(dp));
     
    // Stores count of numbers from
    // [1, L - 1] having K consecutive 1s
    int resL = cntN1X(Ls, 0, K, 0,
                            dp, 0,1);
     
    // Initialize dp[][][][] array.
    memset(dp, -1, sizeof(dp));
     
     
    // Stores count of numbers from
    // [1, R - 1] having K consecutive 1s
    int resR = cntN1X(Rs, 0, K, 0,
                            dp, 0, 1);
     
    // Return total counts having K
    // consecutive 1s in range[L, R]
    return (resR - resL);
}
 
// Driver Code
int main()
{
    int L = 8;
    int R = 100;
    int K = 3;
    cout<<cntN1XL_R(L, R, K);
     
}

Java




// Java program to implement
// the above approach
import java.util.*;
 
class GFG{
     
// Function to find the count of numbers in
// range[1, X] having K consecutive set bits
public static int cntN1X(String str, int len, int K,
                         int cntOne, int dp[][][][],
                         int KOne, int tight)
{
     
    // If length of current number is
    // equal to length of string
    if (len == str.length())
    {
         
        // If count of consecutive set bits
        // in the current string is >= K
        return (KOne == 1) ? 1 : 0;
    }
 
    // If already computedx
    // equal occurred
    if (dp[len][cntOne][KOne][tight] != -1)
    {
        return dp[len][cntOne][KOne][tight];
    }
 
    // If tight is 1, then element present
    // at current index is element present
    // in str at current index. Otherwise, 1.
    int end = (tight == 1) ?
              (str.charAt(len) - '0') : 1;
 
    // Stores count of numbers whose
    // len th bit is i.
    int res = 0;
 
    // Iterate over all possible
    // value present at current index.
    for(int i = 0; i <= end; i++)
    {
         
        // Stores count of consecutive 1s
        int temp = (i == 1) ? (cntOne + 1) : 0;
 
        // Update res.
        res += cntN1X(str, len + 1, K, temp, dp,
                     (int)(KOne | ((temp == K) ? 1 : 0)),
                     (int)(tight & ((i == end) ? 1 : 0)));
    }
    return dp[len][cntOne][KOne][tight] = res;
}
 
// Function to count numbers in
// range[L, R] having K consecutive 1s.
public static int cntN1XL_R(int L, int R, int K)
{
     
    // Stores binary representation
    // of (L - 1)
    String Ls = Integer.toBinaryString(L - 1);
 
    // Stores binary representation
    // of R
    String Rs = Integer.toBinaryString(R);
 
    // Stores values of overlapping
    // subproblems
    int dp[][][][] = new int[32][32][2][2];
 
    // Initialize dp[][][][] array.
    for(int i[][][] : dp)
        for(int j[][] : i)
            for(int k[] : j)
                Arrays.fill(k, -1);
 
    // Stores count of numbers from
    // [1, L - 1] having K consecutive 1s
    int resL = cntN1X(Ls, 0, K, 0, dp, 0, 1);
 
    // Initialize dp[][][][] array.
    for(int i[][][] : dp)
        for(int j[][] : i)
            for(int k[] : j)
                Arrays.fill(k, -1);
 
    // Stores count of numbers from
    // [1, R - 1] having K consecutive 1s
    int resR = cntN1X(Rs, 0, K, 0, dp, 0, 1);
 
    // Return total counts having K
    // consecutive 1s in range[L, R]
    return (resR - resL);
}
 
// Driver Code
public static void main(String args[])
{
    int L = 8;
    int R = 100;
    int K = 3;
     
    System.out.println(cntN1XL_R(L, R, K));
}
}
 
// This code is contributed by hemanth gadarla

Python3




# Python3 program to implement
# the above approach
  
# Function to find the count of numbers in
# range[1, X] having K consecutive set bits
def cntN1X(stri, leng, K, cntOne, dp, KOne, tight):
 
    # If length of current number is
    # equal to length of string
    if (leng == len(stri)):
          
        # If count of consecutive set bits
        # in the current string is >= K
        return 1 if (KOne == 1) else 0;
          
    # If already computedx
    # equal occurred
    if (dp[leng][cntOne][KOne][tight]  != -1):
        return dp[leng][cntOne][KOne][tight];
      
    # If tight is 1, then element present
    # at current index is element present
    # in stri at current index. Otherwise, 1.
    end = (ord(stri[leng]) - ord('0')) if tight == 1 else 1;
      
    # Stores count of numbers whose
    # leng th bit is i.
    res = 0;
      
    # Iterate over all possible
    # value present at current index.
    for i in range(end + 1):
          
        # Stores count of consecutive 1s
        temp = (cntOne + 1) if (i == 1) else 0;
          
        # Update res.
        res += cntN1X(stri, leng + 1,
        K, temp, dp, 1 if(KOne | (temp == K)) else 0,
                    1 if(tight & (i == end)) else 0);
     
    dp[leng][cntOne][KOne][tight]= res
    return res
  
# Function to find
# binary representation of N
def convertBinary(N):
 
    # Stores binary
    # representation of N.
    res=''
      
    # Traverse each bit of N.
    while(N != 0):
          
        # Append current bit
        # in res
        res += chr((N % 2) + ord('0'));
          
        # Update N.
        N //= 2;
         
    # Append 0 in binary representation
    # Of N
    while(len(res) < 32):
        res += '0';
          
    # Reverse binary representation of N
    return res[::-1];
 
# Function to count numbers in
# range[L, R] having K consecutive 1s.
def cntN1XL_R(L, R, K):
 
    # Stores binary representation
    # of (L - 1)
    Ls = str(convertBinary(L - 1));
      
    # Stores binary representation
    # of R
    Rs = str(convertBinary(R));
      
    # Stores values of overlapping
    # subproblems
    dp =[[[[-1,-1] for j in range(2)] for k in range(32)] for l in range(32)]
      
    # Stores count of numbers from
    # [1, L - 1] having K consecutive 1s
    resL = cntN1X(Ls, 0, K, 0, dp, 0,1);
          
    # Initialize dp[][][][] array.
    dp = [[[[-1, -1] for j in range(2)] for k in range(32)] for l in range(32)]
          
    # Stores count of numbers from
    # [1, R - 1] having K consecutive 1s
    resR = cntN1X(Rs, 0, K, 0,
                            dp, 0, 1);
      
    # Return total counts having K
    # consecutive 1s in range[L, R]
    return (resR - resL);
  
# Driver Code
if __name__=='__main__':
     
    L = 8;
    R = 100;
    K = 3;
    print(cntN1XL_R(L, R, K))
     
# This code is contributed by rutvik_56

C#




// C# program to implement
// the above approach
using System;
 
class GFG{
     
// Function to find the count of numbers in
// range[1, X] having K consecutive set bits
public static int cntN1X(String str, int len, int K,
                         int cntOne, int [,,,]dp,
                         int KOne, int tight)
{
     
    // If length of current number is
    // equal to length of string
    if (len == str.Length)
    {
         
        // If count of consecutive set bits
        // in the current string is >= K
        return (KOne == 1) ? 1 : 0;
    }
     
    // If already computedx
    // equal occurred
    if (dp[len, cntOne, KOne, tight] != -1)
    {
        return dp[len, cntOne, KOne, tight];
    }
     
    // If tight is 1, then element present
    // at current index is element present
    // in str at current index. Otherwise, 1.
    int end = (tight == 1) ?
              (str[len] - '0') : 1;
 
    // Stores count of numbers whose
    // len th bit is i.
    int res = 0;
 
    // Iterate over all possible
    // value present at current index.
    for(int i = 0; i <= end; i++)
    {
         
        // Stores count of consecutive 1s
        int temp = (i == 1) ? (cntOne + 1) : 0;
 
        // Update res.
        res += cntN1X(str, len + 1, K, temp, dp,
                     (int)(KOne | ((temp == K) ? 1 : 0)),
                     (int)(tight & ((i == end) ? 1 : 0)));
    }
    return dp[len, cntOne, KOne, tight] = res;
}
 
// Function to count numbers in
// range[L, R] having K consecutive 1s.
public static int cntN1XL_R(int L, int R, int K)
{
     
    // Stores binary representation
    // of (L - 1)
    String Ls = Convert.ToString(L - 1, 2);
 
    // Stores binary representation
    // of R
    String Rs = Convert.ToString(R, 2);
 
    // Stores values of overlapping
    // subproblems
    int [,,,]dp = new int[ 32, 32, 2, 2 ];
 
    // Initialize [,]dp[,] array.
    for(int i = 0; i < 32; i++)
        for(int j = 0; j < 32; j++)
            for(int k = 0; k < 2; k++)
                for(int l = 0; l < 2; l++)
                    dp[i, j, k, l] = -1;
                     
    // Stores count of numbers from
    // [1, L - 1] having K consecutive 1s
    int resL = cntN1X(Ls, 0, K, 0, dp, 0, 1);
     
    // Initialize [,]dp[,] array.
    for(int i = 0; i < 32; i++)
        for(int j = 0; j < 32; j++)
            for(int k = 0; k < 2; k++)
                for(int l = 0; l < 2; l++)
                    dp[i, j, k, l] = -1;
                     
    // Stores count of numbers from
    // [1, R - 1] having K consecutive 1s
    int resR = cntN1X(Rs, 0, K, 0, dp, 0, 1);
     
    // Return total counts having K
    // consecutive 1s in range[L, R]
    return (resR - resL);
}
 
// Driver Code
public static void Main(String []args)
{
    int L = 8;
    int R = 100;
    int K = 3;
     
    Console.WriteLine(cntN1XL_R(L, R, K));
}
}
 
// This code is contributed by gauravrajput1
Output
27

Time complexity: O(322 * 23)
Auxiliary Space: O(322 * 22)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer DSA Live Classes




My Personal Notes arrow_drop_up
Recommended Articles
Page :