Open In App

Queries to count array elements from a given range having a single set bit

Last Updated : 15 Nov, 2021
Comments
Improve
Suggest changes
Like Article
Like
Report

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[c].first;
        int r = queries[c].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[c][0]
        r = queries[c][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[c][0];
        var r = queries[c][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> 

Output: 
6 4

 

Time Complexity: O(N*log(max(arr[i])))
Auxiliary Space: O(N)


 


Next Article

Similar Reads