给定一个由N 个整数和Q 个查询组成的数组arr[] ,每个查询有两个整数L和R ,任务是找到在 L 到 R 范围内具有最大设置位的元素。
注意:如果有多个元素具有最大设置位,则打印其中的最大值。
例子:
Input: arr[] = {18, 9, 8, 15, 14, 5}, Q = {{1, 4}}
Output: 15
Explanation:
Subarray – {9, 8, 15, 14}
Binary Representation of these integers –
9 => 1001 => Set Bits = 2
8 => 1000 => Set Bits = 1
15 => 1111 => Set Bits = 4
14 => 1110 => Set Bits = 3
Therefore, element with maximum set bits is 15.
Input: arr[] = {18, 9, 8, 15, 14, 5}, Q = {{0, 2}}
Output: 18
Explanation:
Subarray – {18, 9, 8}
Binary Representation of these integers –
18 => 10010 => Set Bits = 2
9 => 1001 => Set Bits = 2
8 => 1000 => Set Bits = 1
Therefore, element with maximum set bits is maximum of 18 and 9, which is 18.
朴素的方法:一个简单的解决方案是运行从 L 到 R 的循环并计算每个元素的设置位数,并为每个查询找到从 L 到 R 的最大设置位元素。
时间复杂度:O(Q * N)
辅助空间复杂度:O(1)
有效的方法:想法是使用段树,其中每个节点包含两个值,具有最大设置位的元素和最大设置位的计数。
- 段树的表示:
- 叶节点是给定数组的元素。
- 每个内部节点代表叶节点的一些合并。对于不同的问题,合并可能会有所不同。对于这个问题,合并是节点下叶子的 max_set_bits 的最大值。
- 树的数组表示用于表示段树。对于索引 i 处的每个节点,左子节点在索引2*i+1 处,右子节点在2*i+2 处,父节点在(i-1)/2 处。
- 从给定数组构建段树:
- 我们从一个段 arr[0 开始。 . . n-1]。并且每次我们将当前段分成两半(如果它还没有成为长度为1的段),然后在两半上调用相同的过程,对于每个这样的段,我们将max_set_bits和值存储在对应的节点。
- 任何两个范围组合的最大设置位将是左侧的最大设置位或右侧的最大设置位,以最大值为准。
- 最后,计算段树上的范围查询。
下面是上述方法的实现:
C++
// C++ implementation to find
// maximum set bits value in a range
#include
using namespace std;
// Structure to store two
// values in one node
struct Node {
int value;
int max_set_bits;
};
Node tree[4 * 10000];
// Function that returns the count
// of set bits in a number
int setBits(int x)
{
// Parity will store the
// count of set bits
int parity = 0;
while (x != 0) {
if (x & 1)
parity++;
x = x >> 1;
}
return parity;
}
// Function to build the segment tree
void buildSegmentTree(int a[], int index,
int beg, int end)
{
// Condition to check if there is
// only one element in the array
if (beg == end) {
tree[index].value = a[beg];
tree[index].max_set_bits
= setBits(a[beg]);
}
else {
int mid = (beg + end) / 2;
// If there are more than one elements,
// then recur for left and right subtrees
buildSegmentTree(a, 2 * index + 1,
beg, mid);
buildSegmentTree(a, 2 * index + 2,
mid + 1, end);
// Condition to check the maximum set
// bits is greater in two subtrees
if (tree[2 * index + 1].max_set_bits
> tree[2 * index + 2].max_set_bits) {
tree[index].max_set_bits
= tree[2 * index + 1]
.max_set_bits;
tree[index].value
= tree[2 * index + 1]
.value;
}
else if (tree[2 * index + 2].max_set_bits
> tree[2 * index + 1].max_set_bits) {
tree[index].max_set_bits
= tree[2 * index + 2]
.max_set_bits;
tree[index].value
= tree[2 * index + 2].value;
}
// Condition when maximum set bits
// are equal in both subtrees
else {
tree[index].max_set_bits
= tree[2 * index + 2]
.max_set_bits;
tree[index].value = max(
tree[2 * index + 2].value,
tree[2 * index + 1].value);
}
}
}
// Function to do the range query
// in the segment tree
Node query(int index, int beg,
int end, int l, int r)
{
Node result;
result.value
= result.max_set_bits = -1;
// If segment of this node is outside the given
// range, then return the minimum value.
if (beg > r || end < l)
return result;
// If segment of this node is a part of given
// range, then return the node of the segment
if (beg >= l && end <= r)
return tree[index];
int mid = (beg + end) / 2;
// If left segment of this node falls out of
// range, then recur in the right side of
// the tree
if (l > mid)
return query(2 * index + 2, mid + 1,
end, l, r);
// If right segment of this node falls out of
// range, then recur in the left side of
// the tree
if (r <= mid)
return query(2 * index + 1, beg,
mid, l, r);
// If a part of this segment overlaps with
// the given range
Node left = query(2 * index + 1, beg,
mid, l, r);
Node right = query(2 * index + 2, mid + 1,
end, l, r);
if (left.max_set_bits > right.max_set_bits) {
result.max_set_bits = left.max_set_bits;
result.value = left.value;
}
else if (right.max_set_bits > left.max_set_bits) {
result.max_set_bits = right.max_set_bits;
result.value = right.value;
}
else {
result.max_set_bits = left.max_set_bits;
result.value = max(right.value, left.value);
}
// Returns the value
return result;
}
// Driver code
int main()
{
int a[] = { 18, 9, 8, 15, 14, 5 };
// Calculates the length of array
int N = sizeof(a) / sizeof(a[0]);
// Build Segment Tree
buildSegmentTree(a, 0, 0, N - 1);
// Find the max set bits value between
// 1st and 4th index of array
cout << query(0, 0, N - 1, 1, 4).value
<< endl;
// Find the max set bits value between
// 0th and 2nd index of array
cout << query(0, 0, N - 1, 0, 2).value
<< endl;
return 0;
}
Java
// Java implementation to find
// maximum set bits value in a range
import java.util.*;
class GFG{
// Structure to store two
// values in one node
static class Node
{
int value;
int max_set_bits;
};
static Node []tree = new Node[4 * 10000];
// Function that returns the count
// of set bits in a number
static int setBits(int x)
{
// Parity will store the
// count of set bits
int parity = 0;
while (x != 0)
{
if (x % 2 == 1)
parity++;
x = x >> 1;
}
return parity;
}
// Function to build the segment tree
static void buildSegmentTree(int a[], int index,
int beg, int end)
{
// Condition to check if there is
// only one element in the array
if (beg == end)
{
tree[index].value = a[beg];
tree[index].max_set_bits = setBits(a[beg]);
}
else
{
int mid = (beg + end) / 2;
// If there are more than one elements,
// then recur for left and right subtrees
buildSegmentTree(a, 2 * index + 1,
beg, mid);
buildSegmentTree(a, 2 * index + 2,
mid + 1, end);
// Condition to check the maximum set
// bits is greater in two subtrees
if (tree[2 * index + 1].max_set_bits >
tree[2 * index + 2].max_set_bits)
{
tree[index].max_set_bits =
tree[2 * index + 1].max_set_bits;
tree[index].value =
tree[2 * index + 1].value;
}
else if (tree[2 * index + 2].max_set_bits >
tree[2 * index + 1].max_set_bits)
{
tree[index].max_set_bits =
tree[2 * index + 2].max_set_bits;
tree[index].value =
tree[2 * index + 2].value;
}
// Condition when maximum set bits
// are equal in both subtrees
else
{
tree[index].max_set_bits =
tree[2 * index + 2].max_set_bits;
tree[index].value = Math.max(
tree[2 * index + 2].value,
tree[2 * index + 1].value);
}
}
}
// Function to do the range query
// in the segment tree
static Node query(int index, int beg,
int end, int l, int r)
{
Node result = new Node();
result.value = result.max_set_bits = -1;
// If segment of this node is outside the given
// range, then return the minimum value.
if (beg > r || end < l)
return result;
// If segment of this node is a part of given
// range, then return the node of the segment
if (beg >= l && end <= r)
return tree[index];
int mid = (beg + end) / 2;
// If left segment of this node falls out of
// range, then recur in the right side of
// the tree
if (l > mid)
return query(2 * index + 2, mid + 1,
end, l, r);
// If right segment of this node falls out of
// range, then recur in the left side of
// the tree
if (r <= mid)
return query(2 * index + 1, beg,
mid, l, r);
// If a part of this segment overlaps with
// the given range
Node left = query(2 * index + 1, beg,
mid, l, r);
Node right = query(2 * index + 2, mid + 1,
end, l, r);
if (left.max_set_bits > right.max_set_bits)
{
result.max_set_bits = left.max_set_bits;
result.value = left.value;
}
else if (right.max_set_bits > left.max_set_bits)
{
result.max_set_bits = right.max_set_bits;
result.value = right.value;
}
else
{
result.max_set_bits = left.max_set_bits;
result.value = Math.max(right.value,
left.value);
}
// Returns the value
return result;
}
// Driver code
public static void main(String[] args)
{
int a[] = { 18, 9, 8, 15, 14, 5 };
// Calculates the length of array
int N = a.length;
for(int i = 0; i < tree.length; i++)
tree[i] = new Node();
// Build Segment Tree
buildSegmentTree(a, 0, 0, N - 1);
// Find the max set bits value between
// 1st and 4th index of array
System.out.print(query(0, 0, N - 1, 1, 4).value +"\n");
// Find the max set bits value between
// 0th and 2nd index of array
System.out.print(query(0, 0, N - 1, 0, 2).value +"\n");
}
}
// This code is contributed by amal kumar choubey
Python3
# Python3 implementation to find
# maximum set bits value in a range
# Structure to store two
# values in one node
from typing import List
class Node:
def __init__(self) -> None:
self.value = 0
self.max_set_bits = 0
tree = [Node() for _ in range(4 * 10000)]
# Function that returns the count
# of set bits in a number
def setBits(x: int) -> int:
# Parity will store the
# count of set bits
parity = 0
while (x != 0):
if (x & 1):
parity += 1
x = x >> 1
return parity
# Function to build the segment tree
def buildSegmentTree(a: List[int], index: int,
beg: int, end: int) -> None:
# Condition to check if there is
# only one element in the array
if (beg == end):
tree[index].value = a[beg]
tree[index].max_set_bits = setBits(a[beg])
else:
mid = (beg + end) // 2
# If there are more than one elements,
# then recur for left and right subtrees
buildSegmentTree(a, 2 * index + 1, beg, mid)
buildSegmentTree(a, 2 * index + 2, mid + 1, end)
# Condition to check the maximum set
# bits is greater in two subtrees
if (tree[2 * index + 1].max_set_bits >
tree[2 * index + 2].max_set_bits):
tree[index].max_set_bits = tree[2 * index + 1].max_set_bits
tree[index].value = tree[2 * index + 1].value
elif (tree[2 * index + 2].max_set_bits >
tree[2 * index + 1].max_set_bits):
tree[index].max_set_bits = tree[2 * index + 2].max_set_bits
tree[index].value = tree[2 * index + 2].value
# Condition when maximum set bits
# are equal in both subtrees
else:
tree[index].max_set_bits = tree[2 * index + 2].max_set_bits
tree[index].value = max(tree[2 * index + 2].value,
tree[2 * index + 1].value)
# Function to do the range query
# in the segment tree
def query(index: int, beg: int,
end: int, l: int, r: int) -> Node:
result = Node()
result.value = result.max_set_bits = -1
# If segment of this node is outside the given
# range, then return the minimum value.
if (beg > r or end < l):
return result
# If segment of this node is a part of given
# range, then return the node of the segment
if (beg >= l and end <= r):
return tree[index]
mid = (beg + end) // 2
# If left segment of this node falls out of
# range, then recur in the right side of
# the tree
if (l > mid):
return query(2 * index + 2, mid + 1,
end, l, r)
# If right segment of this node falls out of
# range, then recur in the left side of
# the tree
if (r <= mid):
return query(2 * index + 1, beg,
mid, l, r)
# If a part of this segment overlaps with
# the given range
left = query(2 * index + 1, beg, mid, l, r)
right = query(2 * index + 2, mid + 1, end, l, r)
if (left.max_set_bits > right.max_set_bits):
result.max_set_bits = left.max_set_bits
result.value = left.value
elif (right.max_set_bits > left.max_set_bits):
result.max_set_bits = right.max_set_bits
result.value = right.value
else:
result.max_set_bits = left.max_set_bits
result.value = max(right.value, left.value)
# Returns the value
return result
# Driver code
if __name__ == "__main__":
a = [ 18, 9, 8, 15, 14, 5 ]
# Calculates the length of array
N = len(a)
# Build Segment Tree
buildSegmentTree(a, 0, 0, N - 1)
# Find the max set bits value between
# 1st and 4th index of array
print(query(0, 0, N - 1, 1, 4).value)
# Find the max set bits value between
# 0th and 2nd index of array
print(query(0, 0, N - 1, 0, 2).value)
# This code is contributed by sanjeev2552
C#
// C# implementation to find maximum
// set bits value in a range
using System;
class GFG{
// Structure to store two
// values in one node
class Node
{
public int value;
public int max_set_bits;
};
static Node []tree = new Node[4 * 10000];
// Function that returns the count
// of set bits in a number
static int setBits(int x)
{
// Parity will store the
// count of set bits
int parity = 0;
while (x != 0)
{
if (x % 2 == 1)
parity++;
x = x >> 1;
}
return parity;
}
// Function to build the segment tree
static void buildSegmentTree(int []a, int index,
int beg, int end)
{
// Condition to check if there is
// only one element in the array
if (beg == end)
{
tree[index].value = a[beg];
tree[index].max_set_bits = setBits(a[beg]);
}
else
{
int mid = (beg + end) / 2;
// If there are more than one elements,
// then recur for left and right subtrees
buildSegmentTree(a, 2 * index + 1,
beg, mid);
buildSegmentTree(a, 2 * index + 2,
mid + 1, end);
// Condition to check the maximum set
// bits is greater in two subtrees
if (tree[2 * index + 1].max_set_bits >
tree[2 * index + 2].max_set_bits)
{
tree[index].max_set_bits =
tree[2 * index + 1].max_set_bits;
tree[index].value =
tree[2 * index + 1].value;
}
else if (tree[2 * index + 2].max_set_bits >
tree[2 * index + 1].max_set_bits)
{
tree[index].max_set_bits =
tree[2 * index + 2].max_set_bits;
tree[index].value =
tree[2 * index + 2].value;
}
// Condition when maximum set bits
// are equal in both subtrees
else
{
tree[index].max_set_bits =
tree[2 * index + 2].max_set_bits;
tree[index].value = Math.Max(
tree[2 * index + 2].value,
tree[2 * index + 1].value);
}
}
}
// Function to do the range query
// in the segment tree
static Node query(int index, int beg,
int end, int l, int r)
{
Node result = new Node();
result.value = result.max_set_bits = -1;
// If segment of this node is outside the given
// range, then return the minimum value.
if (beg > r || end < l)
return result;
// If segment of this node is a part of given
// range, then return the node of the segment
if (beg >= l && end <= r)
return tree[index];
int mid = (beg + end) / 2;
// If left segment of this node falls out of
// range, then recur in the right side of
// the tree
if (l > mid)
return query(2 * index + 2, mid + 1,
end, l, r);
// If right segment of this node falls out of
// range, then recur in the left side of
// the tree
if (r <= mid)
return query(2 * index + 1, beg,
mid, l, r);
// If a part of this segment overlaps with
// the given range
Node left = query(2 * index + 1, beg,
mid, l, r);
Node right = query(2 * index + 2, mid + 1,
end, l, r);
if (left.max_set_bits > right.max_set_bits)
{
result.max_set_bits = left.max_set_bits;
result.value = left.value;
}
else if (right.max_set_bits > left.max_set_bits)
{
result.max_set_bits = right.max_set_bits;
result.value = right.value;
}
else
{
result.max_set_bits = left.max_set_bits;
result.value = Math.Max(right.value,
left.value);
}
// Returns the value
return result;
}
// Driver code
public static void Main(String[] args)
{
int []a = { 18, 9, 8, 15, 14, 5 };
// Calculates the length of array
int N = a.Length;
for(int i = 0; i < tree.Length; i++)
tree[i] = new Node();
// Build Segment Tree
buildSegmentTree(a, 0, 0, N - 1);
// Find the max set bits value between
// 1st and 4th index of array
Console.Write(query(0, 0, N - 1, 1, 4).value + "\n");
// Find the max set bits value between
// 0th and 2nd index of array
Console.Write(query(0, 0, N - 1, 0, 2).value + "\n");
}
}
// This code is contributed by amal kumar choubey
15
18
时间复杂度: O(Q * logN)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。