📜  计算 [L, R] 范围内具有 K 个连续设置位的数字

📅  最后修改于: 2021-09-22 10:22:51             🧑  作者: Mango

给定三个正整数LRK ,任务是找到范围[L, R]中在其二进制表示中有K个连续设置位的数字的计数。

例子:

朴素方法:解决此问题的最简单方法是遍历范围[L, R]内所有可能的整数,并针对每个数字检查该数字的二进制表示是否包含 K 个连续的 1。如果发现是真的,则打印数字。

时间复杂度: O((R – L + 1) * 32)
辅助空间: O(1)

高效方法:该问题可以使用 Digit DP 解决。这个想法是计算[1, R]范围内具有K个连续1的数字,并减去范围[1, L – 1] 中具有K个连续1的数字的计数。以下是递推关系:

请按照以下步骤解决问题:

  • 初始化一个 4D 数组dp[len][cntOne][KOne][tight]来计算和存储上述递推关系的所有子问题的值。
  • 最后,返回dp[len][cntOne][KOne][tight] 的值

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
 
#include 
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<


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


Javascript


输出
27

时间复杂度: O(32 2 * 2 3 )
辅助空间: O(32 2 * 2 2 )

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程