Queries to count array elements from a given range having a single set bit
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++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // Function to check whether // only one bit is set or not int check( int x) { if (((x) & (x - 1)) == 0) return 1; return 0; } // Function to perform Range-query int query( int l, int r, int pre[]) { if (l == 0) return pre[r]; else return pre[r] - pre[l - 1]; } // Function to count array elements with a // single set bit for each range in a query void countInRange( int arr[], int N, vector<pair< int , int > > queries, int Q) { // Initialize array for Prefix sum 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) << ' ' ; } } // Driver Code int main() { // Given array int arr[] = { 12, 11, 16, 8, 2, 5, 1, 3, 256, 1 }; // Size of the array int N = sizeof (arr) / sizeof (arr[0]); // Given queries vector<pair< int , int > > queries = { { 0, 9 }, { 4, 9 } }; // Size of queries array int Q = queries.size(); countInRange(arr, N, queries, Q); return 0; } |
Java
// JAVA program for the above approach import java.util.*; import java.io.*; import java.math.*; public class GFG { // Function to check whether // only one bit is set or not static int check( int x) { if (((x) & (x - 1 )) == 0 ) return 1 ; return 0 ; } // Function to perform Range-query static int query( int l, int r, int [] pre) { if (l == 0 ) return pre[r]; else return pre[r] - pre[l - 1 ]; } // Function to count array elements with a // single set bit for each range in a query static void countInRange( int [] arr, int N, ArrayList<Pair> queries, int Q) { // Initialize array for Prefix sum 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) + " " ); } } // A Pair class for handling queries in JAVA // As, there is no in-built function of Tuple static class Pair { int item1, item2; Pair( int item1, int item2) { this .item1 = item1; this .item2 = item2; } } // Driver code public static void main(String args[]) { // Given array int [] arr = { 12 , 11 , 16 , 8 , 2 , 5 , 1 , 3 , 256 , 1 }; // Size of the array int N = arr.length; // Given queries ArrayList<Pair> queries = new ArrayList<Pair>(); queries.add( new Pair( 4 , 9 )); queries.add( new Pair( 0 , 9 )); // Size of queries array int Q = queries.size(); countInRange(arr, N, queries, Q); } } // This code is contributed by jyoti369 |
Python3
# Python 3 program for the above approach # Function to check whether # only one bit is set or not def check(x): if (((x) & (x - 1 )) = = 0 ): return 1 return 0 # Function to perform Range-query def query(l, r, pre): if (l = = 0 ): return pre[r] else : return pre[r] - pre[l - 1 ] # Function to count array elements with a # single set bit for each range in a query def countInRange(arr, N, queries, Q): # Initialize array for Prefix sum 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 # Driver Code if __name__ = = "__main__" : # Given array arr = [ 12 , 11 , 16 , 8 , 2 , 5 , 1 , 3 , 256 , 1 ] # Size of the array N = len (arr) # Given queries queries = [[ 0 , 9 ], [ 4 , 9 ]] # Size of queries array Q = len (queries) countInRange(arr, N, queries, Q) # this code is contributed by chitranayal. |
C#
// C# program for the above approach using System; using System.Collections.Generic; class GFG{ // Function to check whether // only one bit is set or not static int check( int x) { if (((x) & (x - 1)) == 0) return 1; return 0; } // Function to perform Range-query static int query( int l, int r, int [] pre) { if (l == 0) return pre[r]; else return pre[r] - pre[l - 1]; } // Function to count array elements with a // single set bit for each range in a query static void countInRange( int [] arr, int N, List<Tuple< int , int >> queries, int Q) { // Initialize array for Prefix sum 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) + " " ); } } // Driver code static void Main() { // Given array int [] arr = { 12, 11, 16, 8, 2, 5, 1, 3, 256, 1 }; // Size of the array int N = arr.Length; // Given queries 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)); // Size of queries array int Q = queries.Count; countInRange(arr, N, queries, Q); } } // This code is contributed by divyeshrabadiya07 |
Javascript
<script> // JavaScript program for the above approach // Function to check whether // only one bit is set or not function check(x) { if (((x) & (x - 1)) == 0) return 1; return 0; } // Function to perform Range-query function query(l, r, pre) { if (l == 0) return pre[r]; else return pre[r] - pre[l - 1]; } // Function to count array elements with a // single set bit for each range in a query function countInRange(arr, N, queries, Q) { // Initialize array for Prefix sum 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) + ' ' ); } } // Driver Code // Given array var arr = [12, 11, 16, 8, 2, 5, 1, 3, 256, 1]; // Size of the array var N = arr.length; // Given queries var queries = [[0, 9], [4, 9 ]]; // Size of queries array var Q = queries.length; countInRange(arr, N, queries, Q); </script> |
6 4
Time Complexity: O(N*log(max(arr[i])))
Auxiliary Space: O(N)
Please Login to comment...