Queries for number of array elements in a range with Kth Bit Set using C++

C++Server Side ProgrammingProgramming

In this article we will discuss a problem of finding the number of elements present in the given range that have a kth bit set, for example −

Input : arr[] = { 4, 5, 7, 2 }
Query 1: L = 2, R = 4, K = 4
Query 2: L = 3, R = 5, K = 1
Output :
   0
   1

We are going to solve this problem by a brute force approach and see if this approach can work for higher constraints or not. If not, then we try to think of a new efficient approach.

Brute Force Approach

In this approach, we are simply going to go through the range and check for each element that if it’s kth bit is set or not, if yes, then we increase the count.

Example

#include<bits/stdc++.h>
using namespace std;
#define MAX_BITS 32
bool Kset(int n, int k) { // to check if kth bit is set
   if (n & (1 << (k - 1)))
   return true;
   return false;
}
int query(int L, int R, int K, int arr[]) {
   int count = 0; // counter to keep count of number present in the range
   for (int i = L; i <= R; i++) { // traversing the range
      if (Kset(arr[i], K)) {
         count++;
      }
   }
   return count;
}
int main() {
   int arr[] = { 4, 5, 7, 2 }; // given array
   int n = sizeof(arr) / sizeof(arr[0]); // size of our array
   int queries[][3] = { // given L, R and k
      { 2, 4, 4 },
      { 3, 5, 1 }
   };
   int q = sizeof(queries) / sizeof(queries[0]); // number of queries

   for (int i = 0; i < q; i++) {
      int L = queries[i][0] - 1;
      int R = queries[i][1] - 1;
      int K = queries[i][2];

      cout << query(L, R, K, arr) << "\n";
   }
   return 0;
}

Output

0
1

The above approach has a time complexity of O(N*Q) where N is the size of our array and Q is the number of queries we are given now; as you can see, this approach is not suitable for higher constraints as it will take too much time so now we will try to make a program of efficient approach.

Efficient Approach

In this approach, we will maintain a 2-D prefix sum array that will keep the count of every bit used till each index, and then we can calculate the answer in O(1) complexity.

Example

#include<bits/stdc++.h>
using namespace std;
#define bits 32 // number of bits

int P[100000][bits+1];

bool Kset(int n, int k) {
   if (n & (1 << (k - 1)))
      return true;
   return false;
}
void prefixArray(int n, int arr[]) { // building the prefix array
   for (int i = 0; i <= bits; i++) {
      P[0][i] = 0; // setting every bits initial count = 0
   }
   for (int i = 0; i < n; i++) {
      for (int j = 1; j <= bits; j++) {
         bool flag = Kset(arr[i], j);
         if (i) // we add previous count to the latest count(0)
            P[i][j] = P[i - 1][j];
         if (flag) { // if jth bit is set so we increase the count
            P[i][j]++;
         }
      }
   }
}
int query(int L, int R, int K) {
   if (L) // if L not equal to 0 then we return the prefix at R subtracted with prefix at L-1
      return P[R][K] - P[L - 1][K];
   else
      return P[R][K];
}
int main() {
   int arr[] = { 8, 9, 1, 3 }; // given array
   int n = sizeof(arr) / sizeof(arr[0]); // size of given array
   int queries[][3] = {
      { 1, 3, 4 },
      { 2, 4, 1 }
   };
   prefixArray(n, arr); // calling the function to create prefix array
   int q = sizeof(queries) / sizeof(queries[0]); // number of queries

   for (int i = 0; i < q; i++) {
      int L = queries[i][0] - 1;
      int R = queries[i][1] - 1;
      int K = queries[i][2];
      cout << query(L, R, K) << "\n";
   }
   return 0;
}

Output

2
3

As we are maintaining the prefix array that is helping us in finding the answer in O(1) So by this, our time complexity is drastically reduced to O(N), where N is the size of our given array.

Explanation of the above code

In this program, we maintain a prefix counter for every index of the array that counts every bit used until the index. We build this count for our array now as we have the prefix count of every bit stored with us, so for kth bit count, we need to subtract the prefix count of kth bit till R index with the prefix count of kth bit till L-1 index and that are our answer.

Conclusion

In this article, we solve a problem to solve Queries for the number of array elements in a range with the Kth Bit Set. We also learned the C++ program for this problem and the complete approach ( Normal and efficient ) by which we solved this problem.We can write the same program in other languages such as C, java, python, and other languages. We hope you find this article helpful.

raja
Published on 26-Nov-2021 09:54:19

Advertisements