2080.区间内查询数字的频率
binary search, segment tree, https://leetcode.cn/problems/range-frequency-queries/
为了解决这个问题,需要设计一个数据结构来高效地查询子数组中某个值的频率。直接对每个查询都遍历一次子数组会导致时间复杂度过高,因此需要优化查询效率。
思路:
预处理 arr 数组中的每个元素的索引,以便在查询时能够高效地返回频率。具体来说,我们可以:
- 预处理阶段:
- 使用一个字典
value_to_indices,它的键是数组中元素的值,值是一个列表,存储该值在数组中出现的所有下标。 - 这样,对于每个查询,我们只需要查找该值的所有出现位置,并通过二分查找来快速计算某个范围内的频率。
- 使用一个字典
- 查询阶段:
- 对于每个查询
(left, right, value),我们使用value_to_indices中存储的该值的所有下标,利用二分查找来找到在给定范围内的元素数量。
- 对于每个查询
这样,查询可以在 O(log n) 的时间复杂度内完成,因为我们可以通过二分查找快速找到子数组的范围。
代码实现:
python
from bisect import bisect_left, bisect_right
class RangeFreqQuery:
def __init__(self, arr):
# 预处理:构建值到索引列表的映射
self.value_to_indices = {}
for i, num in enumerate(arr):
if num not in self.value_to_indices:
self.value_to_indices[num] = []
self.value_to_indices[num].append(i)
def query(self, left, right, value):
# 如果该值在数组中没有出现,直接返回0
if value not in self.value_to_indices:
return 0
indices = self.value_to_indices[value]
# 使用二分查找找到左边界和右边界
left_idx = bisect_left(indices, left)
right_idx = bisect_right(indices, right)
# 返回在区间 [left, right] 内的频率
return right_idx - left_idx时间复杂度分析:
- 初始化:构造
value_to_indices字典的时间复杂度为O(n),其中n是数组的长度。 - 查询:每次查询的时间复杂度为
O(log n),因为我们使用了二分查找来找到区间内的频率。
因此,整体的时间复杂度对于每次查询都是 O(log n),非常高效。
空间复杂度:
- 空间复杂度为
O(n),存储了每个值的索引列表。
这种方法可以处理大规模数据和多次查询,适用于查询频繁的场景。