1865. 找出和为指定值的下标对

支持累加与计数查询的数据结构设计 —— LeetCode 题解

题目描述

给你两个整数数组 nums1nums2,请你实现一个数据结构 FindSumPairs,支持以下两类操作:

  • 累加操作:将一个正整数加到 nums2 中指定下标对应元素上。
  • 计数操作:统计满足 nums1[i] + nums2[j] == tot 的下标对 (i, j) 数目,其中 0 <= i < nums1.length0 <= j < nums2.length

具体来说,实现类 FindSumPairs

  • FindSumPairs(int[] nums1, int[] nums2):使用数组 nums1nums2 初始化对象。
  • 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) 查询,可以利用频率统计快速匹配目标值。

核心思想:

  1. 用哈希表 freq1 统计 nums1 中每个数字的频率。
  2. 用哈希表 freq2 统计当前 nums2 中每个数字的频率。
  3. 当执行 add(index, val) 时:
    • 找到 nums2[index] 的旧值 old_val,将 freq2[old_val] 减一。
    • 更新 nums2[index] 新值 new_val = old_val + val,将 freq2[new_val] 加一。
  4. 当执行 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
  • 调用 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

总结

  • 通过维护两个数组数字的频率表,利用哈希表统计数据,避免了频繁遍历整个二维数组。
  • add 操作是 O(1),count 操作根据 nums1 不同元素个数调整时间复杂度。
  • 该方案适合 nums1 不变且元素种类有限的场景。
  • 思路清晰,代码简洁易懂,是解决类似问题的通用技巧。

你可能感兴趣的:(1865. 找出和为指定值的下标对)