支持累加与计数查询的数据结构设计 —— LeetCode 题解
题目描述
给你两个整数数组 nums1 和 nums2,请你实现一个数据结构 FindSumPairs,支持以下两类操作:
- 累加操作:将一个正整数加到
nums2中指定下标对应元素上。 - 计数操作:统计满足
nums1[i] + nums2[j] == tot的下标对(i, j)数目,其中0 <= i < nums1.length且0 <= j < nums2.length。
具体来说,实现类 FindSumPairs:
FindSumPairs(int[] nums1, int[] nums2):使用数组nums1和nums2初始化对象。void add(int index, int val):将val加到nums2[index]上,即nums2[index] += val。int count(int tot):返回满足nums1[i] + nums2[j] == tot的下标对(i, j)数目。
解题分析
这个问题的难点在于:
nums1是固定数组,不会改变;nums2会频繁执行add操作更新元素值;- 需要快速计算满足条件的
(i, j)对数。
朴素做法是:
add操作直接更新nums2;count操作对所有i, j遍历判断nums1[i] + nums2[j] == tot。
这种方法在 count 查询时时间复杂度达到 O(N * M),显然在数据规模较大时不可接受。
关键点及思路
nums1是固定的,可以预处理统计每个数出现的次数。nums2频繁更新,我们需要一种快速更新元素值和频率的结构。count(tot)查询,可以利用频率统计快速匹配目标值。
核心思想:
- 用哈希表
freq1统计nums1中每个数字的频率。 - 用哈希表
freq2统计当前nums2中每个数字的频率。 - 当执行
add(index, val)时:- 找到
nums2[index]的旧值old_val,将freq2[old_val]减一。 - 更新
nums2[index]新值new_val = old_val + val,将freq2[new_val]加一。
- 找到
- 当执行
count(tot)时,遍历freq1中所有数字x,计算y = tot - x,查找freq2[y],累加freq1[x] * freq2[y]。
解题方法代码实现(Python)
from collections import Counter
from typing import List
class FindSumPairs:
def __init__(self, nums1: List[int], nums2: List[int]):
self.nums1 = nums1
self.nums2 = nums2
# 统计nums1中数字的频率,nums1不变,初始化一次即可
self.freq1 = Counter(nums1)
# 统计nums2中数字的频率,nums2会更新,需要维护
self.freq2 = Counter(nums2)
def add(self, index: int, val: int) -> None:
old_val = self.nums2[index]
# 旧值频率减一
self.freq2[old_val] -= 1
if self.freq2[old_val] == 0:
del self.freq2[old_val]
# 更新nums2中对应元素
new_val = old_val + val
self.nums2[index] = new_val
# 新值频率加一
self.freq2[new_val] = self.freq2.get(new_val, 0) + 1
def count(self, tot: int) -> int:
result = 0
# 对nums1中每个数字x,查找nums2中目标数字y=tot-x
for x in self.freq1:
y = tot - x
if y in self.freq2:
result += self.freq1[x] * self.freq2[y]
return result
复杂度分析
- 初始化:统计频率,时间复杂度 O(N + M),其中 N = len(nums1),M = len(nums2)。
- add 操作:更新
nums2[index]及频率表,时间复杂度 O(1)。 - count 操作:遍历
freq1,查找匹配频率,时间复杂度 O(U),U 为nums1中不同数字的个数。
该方法特别适合 nums1 数字种类不多的情况。如果 nums1 非常大且数字高度离散,count 复杂度会较高。
示例说明
假设:
nums1 = [1, 1, 2]
nums2 = [2, 3]
- 初始化:
- freq1 = {1: 2, 2: 1}
- freq2 = {2: 1, 3: 1}
- 调用
count(4):- 遍历 freq1:
- x=1,y=3,freq2[3]=1,贡献 2 * 1 = 2
- x=2,y=2,freq2[2]=1,贡献 1 * 1 = 1
- 总计 = 3
- 遍历 freq1:
- 调用
add(1, 2):- nums2[1] = 3 -> 5
- freq2 变为 {2:1, 3:0 -> 删除, 5:1}
- 调用
count(7):- 遍历 freq1:
- x=1, y=6, freq2[6]=0,贡献0
- x=2, y=5, freq2[5]=1,贡献 1 * 1 = 1
- 结果是 1
- 遍历 freq1:
总结
- 通过维护两个数组数字的频率表,利用哈希表统计数据,避免了频繁遍历整个二维数组。
add操作是 O(1),count操作根据nums1不同元素个数调整时间复杂度。- 该方案适合
nums1不变且元素种类有限的场景。 - 思路清晰,代码简洁易懂,是解决类似问题的通用技巧。
1161

被折叠的 条评论
为什么被折叠?



