给定一个包含正整数的数组arr []和一个包含查询的数组Q [] [] ,每个第i个查询的任务是对[Q [i] [0],Q [i]范围内的数组元素进行计数[1]仅带有一个置位。
例子:
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
天真的方法:对于每个查询,最简单的方法是使用Brian Kernighan的算法对范围[l,r]进行迭代并计算仅具有一个设置位的数组元素的数量。
时间复杂度:O(Q * N * logN)
辅助空间: O(1)
高效方法:请按照以下步骤优化上述方法:
- 初始化一个前缀和数组,以仅用一个设置位存储元素的数量。
- 第i个索引存储只有第i个索引处的一组置位的数组元素的计数。
- 对于每个查询(i,j) ,返回pre [j] – pre [i – 1] ,即(包含-排除原理)。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
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 > queries, int Q)
{
// Intialize 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 > 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 queries,
int Q)
{
// Intialize 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 queries = new ArrayList();
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):
# Intialize 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> queries,
int Q)
{
// Intialize 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> queries = new List>();
queries.Add(new Tuple(0, 9));
queries.Add(new Tuple(4, 9));
// Size of queries array
int Q = queries.Count;
countInRange(arr, N, queries, Q);
}
}
// This code is contributed by divyeshrabadiya07
6 4
时间复杂度: O(N * log(max(arr [i])))
辅助空间: O(N)