Finding Pairs With a Certain Sum

medium design hash table frequency map

Problem

Design FindSumPairs(nums1, nums2) supporting two operations. add(index, val) does nums2[index] += val. count(tot) returns the number of pairs (i, j) with nums1[i] + nums2[j] == tot. Since nums1 is short but nums2 is long, keep a frequency map of nums2's values: then count sums freq[tot − nums1[i]] over the small array, and add just patches two map entries.

Inputnums1 = [1,1,2,2,2,3], nums2 = [1,4,5,2,5,4]; count(7)
Output8
For each a in nums1 add freq[7−a]: a=1→freq[6]=0, a=2→freq[5]=2 (three times), a=3→freq[4]=2. Total 0+0+2+2+2+2 = 8.

class FindSumPairs:
    def __init__(self, nums1, nums2):
        self.nums1 = nums1
        self.nums2 = nums2
        self.freq = Counter(nums2)        # value -> how many times it appears

    def add(self, index, val):
        old = self.nums2[index]
        self.freq[old] -= 1               # remove the old value
        self.nums2[index] += val          # nums2[index] += val
        self.freq[self.nums2[index]] += 1 # add the new value

    def count(self, tot):
        res = 0
        for a in self.nums1:              # nums1 is short, iterate it
            res += self.freq[tot - a]     # how many nums2[j] equal tot - a
        return res
class FindSumPairs {
  constructor(nums1, nums2) {
    this.nums1 = nums1;
    this.nums2 = nums2;
    this.freq = new Map();                 // value -> count
    for (const v of nums2) this.freq.set(v, (this.freq.get(v) || 0) + 1);
  }
  add(index, val) {
    const old = this.nums2[index];
    this.freq.set(old, this.freq.get(old) - 1);   // remove old value
    this.nums2[index] += val;                       // nums2[index] += val
    const nv = this.nums2[index];
    this.freq.set(nv, (this.freq.get(nv) || 0) + 1); // add new value
  }
  count(tot) {
    let res = 0;
    for (const a of this.nums1)                      // iterate short nums1
      res += this.freq.get(tot - a) || 0;            // count of tot - a
    return res;
  }
}
class FindSumPairs {
    int[] nums1, nums2;
    Map<Integer, Integer> freq = new HashMap<>();   // value -> count
    public FindSumPairs(int[] nums1, int[] nums2) {
        this.nums1 = nums1; this.nums2 = nums2;
        for (int v : nums2) freq.merge(v, 1, Integer::sum);
    }
    public void add(int index, int val) {
        int old = nums2[index];
        freq.merge(old, -1, Integer::sum);          // remove old value
        nums2[index] += val;                        // nums2[index] += val
        freq.merge(nums2[index], 1, Integer::sum);  // add new value
    }
    public int count(int tot) {
        int res = 0;
        for (int a : nums1)                         // iterate short nums1
            res += freq.getOrDefault(tot - a, 0);   // count of tot - a
        return res;
    }
}
class FindSumPairs {
    vector<int> nums1, nums2;
    unordered_map<int,int> freq;                     // value -> count
public:
    FindSumPairs(vector<int>& a, vector<int>& b) : nums1(a), nums2(b) {
        for (int v : nums2) freq[v]++;
    }
    void add(int index, int val) {
        int old = nums2[index];
        freq[old]--;                                // remove old value
        nums2[index] += val;                        // nums2[index] += val
        freq[nums2[index]]++;                       // add new value
    }
    int count(int tot) {
        int res = 0;
        for (int a : nums1)                         // iterate short nums1
            res += freq.count(tot - a) ? freq[tot - a] : 0; // count of tot - a
        return res;
    }
};
Time: init O(n2), count O(n1), add O(1) Space: O(n2)