Queries to count array elements from a given range having a single set bit
Last Updated :
15 Nov, 2021
Given an array arr[] consisting of positive integers and an array Q[][] consisting of queries, the task for every ith query is to count array elements from the range [Q[i][0], Q[i][1]] with only one set bit.
Examples:
Input: arr[] = {12, 11, 16, 8, 2, 5, 1, 3, 256, 1}, queries[][] = {{0, 9}, {4, 9}}
Output: 6 4
Explanation:
In the range of indices [0, 9], the elements arr[2] (= 16), arr[3](= 8), arr[4]( = 2), arr[6](= 1), arr[8](= 256), arr[9](= 1) have only 1 set bit.
In the range [4, 9], the elements arr[4] (= 2), arr[6](= 1), arr[8](= 256), arr[9] (= 1) have only 1 set bit.
Input: arr[] = {2, 1, 101, 11, 4}, queries[][] = {{2, 4}, {1, 4}}
Output: 1 2
Naive Approach: The simplest approach for each query, is to iterate the range [l, r] and count the number of array elements having only one set bit by using Brian Kernighan’s Algorithm.
Time Complexity: O(Q * N*logN)
Auxiliary Space: O(1)
Efficient Approach: Follow the steps below to optimize the above approach:
- Initialize a prefix sum array to store the number of elements with only one set bit.
- The i-th index stores the count of array elements with only one set bit upto the ith index.
- For each query (i, j), return pre[j] – pre[i – 1], i.e. (inclusion-exclusion principle).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int check( int x)
{
if (((x) & (x - 1)) == 0)
return 1;
return 0;
}
int query( int l, int r, int pre[])
{
if (l == 0)
return pre[r];
else
return pre[r] - pre[l - 1];
}
void countInRange( int arr[], int N,
vector<pair< int , int > > queries, int Q)
{
int pre[N] = { 0 };
pre[0] = check(arr[0]);
for ( int i = 1; i < N; i++) {
pre[i] = pre[i - 1] + check(arr[i]);
}
int c = 0;
while (Q--) {
int l = queries.first;
int r = queries.second;
c++;
cout << query(l, r, pre) << ' ' ;
}
}
int main()
{
int arr[] = { 12, 11, 16, 8, 2, 5, 1, 3, 256, 1 };
int N = sizeof (arr) / sizeof (arr[0]);
vector<pair< int , int > > queries
= { { 0, 9 }, { 4, 9 } };
int Q = queries.size();
countInRange(arr, N, queries, Q);
return 0;
}
|
Java
import java.util.*;
import java.io.*;
import java.math.*;
public class GFG
{
static int check( int x)
{
if (((x) & (x - 1 )) == 0 )
return 1 ;
return 0 ;
}
static int query( int l, int r, int [] pre)
{
if (l == 0 )
return pre[r];
else
return pre[r] - pre[l - 1 ];
}
static void countInRange( int [] arr, int N, ArrayList<Pair> queries,
int Q)
{
int [] pre = new int [N];
pre[ 0 ] = check(arr[ 0 ]);
for ( int i = 1 ; i < N; i++)
{
pre[i] = pre[i - 1 ] + check(arr[i]);
}
int c = 0 ;
int q = 0 ;
while (q < Q)
{
int l = queries.get(q).item1;
int r = queries.get(q).item2;
c++;
q++;
System.out.print(query(l, r, pre) + " " );
}
}
static class Pair
{
int item1, item2;
Pair( int item1, int item2)
{
this .item1 = item1;
this .item2 = item2;
}
}
public static void main(String args[])
{
int [] arr = { 12 , 11 , 16 , 8 , 2 ,
5 , 1 , 3 , 256 , 1 };
int N = arr.length;
ArrayList<Pair> queries = new ArrayList<Pair>();
queries.add( new Pair( 4 , 9 ));
queries.add( new Pair( 0 , 9 ));
int Q = queries.size();
countInRange(arr, N, queries, Q);
}
}
|
Python3
def check(x):
if (((x) & (x - 1 )) = = 0 ):
return 1
return 0
def query(l, r, pre):
if (l = = 0 ):
return pre[r]
else :
return pre[r] - pre[l - 1 ]
def countInRange(arr, N, queries, Q):
pre = [ 0 ] * N
pre[ 0 ] = check(arr[ 0 ])
for i in range ( 1 , N):
pre[i] = pre[i - 1 ] + check(arr[i])
c = 0
while (Q > 0 ):
l = queries[ 0 ]
r = queries[ 1 ]
c + = 1
print (query(l, r, pre), end = " " )
Q - = 1
if __name__ = = "__main__" :
arr = [ 12 , 11 , 16 , 8 , 2 , 5 , 1 , 3 , 256 , 1 ]
N = len (arr)
queries = [[ 0 , 9 ], [ 4 , 9 ]]
Q = len (queries)
countInRange(arr, N, queries, Q)
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int check( int x)
{
if (((x) & (x - 1)) == 0)
return 1;
return 0;
}
static int query( int l, int r, int [] pre)
{
if (l == 0)
return pre[r];
else
return pre[r] - pre[l - 1];
}
static void countInRange( int [] arr, int N,
List<Tuple< int , int >> queries,
int Q)
{
int [] pre = new int [N];
pre[0] = check(arr[0]);
for ( int i = 1; i < N; i++)
{
pre[i] = pre[i - 1] + check(arr[i]);
}
int c = 0;
int q = 0;
while (q < Q)
{
int l = queries[q].Item1;
int r = queries[q].Item2;
c++;
q++;
Console.Write(query(l, r, pre) + " " );
}
}
static void Main()
{
int [] arr = { 12, 11, 16, 8, 2,
5, 1, 3, 256, 1 };
int N = arr.Length;
List<Tuple< int ,
int >> queries = new List<Tuple< int ,
int >>();
queries.Add( new Tuple< int , int >(0, 9));
queries.Add( new Tuple< int , int >(4, 9));
int Q = queries.Count;
countInRange(arr, N, queries, Q);
}
}
|
Javascript
<script>
function check(x)
{
if (((x) & (x - 1)) == 0)
return 1;
return 0;
}
function query(l, r, pre)
{
if (l == 0)
return pre[r];
else
return pre[r] - pre[l - 1];
}
function countInRange(arr, N, queries, Q)
{
var pre = Array(N).fill(0);
pre[0] = check(arr[0]);
for ( var i = 1; i < N; i++) {
pre[i] = pre[i - 1] + check(arr[i]);
}
var c = 0;
while (Q--) {
var l = queries[0];
var r = queries[1];
c++;
document.write( query(l, r, pre) + ' ' );
}
}
var arr = [12, 11, 16, 8, 2, 5, 1, 3, 256, 1];
var N = arr.length;
var queries
= [[0, 9], [4, 9 ]];
var Q = queries.length;
countInRange(arr, N, queries, Q);
</script>
|
Time Complexity: O(N*log(max(arr[i])))
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...