Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given two integer arrays nums1 and nums2. You are tasked to implement a data structure that supports queries of two types:
nums2.(i, j) such that nums1[i] + nums2[j] equals a given value (0 <= i < nums1.length and 0 <= j < nums2.length).Implement the FindSumPairs class:
FindSumPairs(int[] nums1, int[] nums2) Initializes the FindSumPairs object with two integer arrays nums1 and nums2.void add(int index, int val) Adds val to nums2[index], i.e., apply nums2[index] += val.int count(int tot) Returns the number of pairs (i, j) such that nums1[i] + nums2[j] == tot.Example 1:
Input ["FindSumPairs", "count", "add", "count", "count", "add", "add", "count"] [[[1, 1, 2, 2, 2, 3], [1, 4, 5, 2, 5, 4]], [7], [3, 2], [8], [4], [0, 1], [1, 1], [7]] Output [null, 8, null, 2, 1, null, null, 11] Explanation FindSumPairs findSumPairs = new FindSumPairs([1, 1, 2, 2, 2, 3], [1, 4, 5, 2, 5, 4]); findSumPairs.count(7); // return 8; pairs (2,2), (3,2), (4,2), (2,4), (3,4), (4,4) make 2 + 5 and pairs (5,1), (5,5) make 3 + 4 findSumPairs.add(3, 2); // now nums2 = [1,4,5,4,5,4] findSumPairs.count(8); // return 2; pairs (5,2), (5,4) make 3 + 5 findSumPairs.count(4); // return 1; pair (5,0) makes 3 + 1 findSumPairs.add(0, 1); // now nums2 = [2,4,5,4,5,4] findSumPairs.add(1, 1); // now nums2 = [2,5,5,4,5,4] findSumPairs.count(7); // return 11; pairs (2,1), (2,2), (2,4), (3,1), (3,2), (3,4), (4,1), (4,2), (4,4) make 2 + 5 and pairs (5,3), (5,5) make 3 + 4
Constraints:
1 <= nums1.length <= 10001 <= nums2.length <= 1051 <= nums1[i] <= 1091 <= nums2[i] <= 1050 <= index < nums2.length1 <= val <= 1051 <= tot <= 1091000 calls are made to add and count each.Problem summary: You are given two integer arrays nums1 and nums2. You are tasked to implement a data structure that supports queries of two types: Add a positive integer to an element of a given index in the array nums2. Count the number of pairs (i, j) such that nums1[i] + nums2[j] equals a given value (0 <= i < nums1.length and 0 <= j < nums2.length). Implement the FindSumPairs class: FindSumPairs(int[] nums1, int[] nums2) Initializes the FindSumPairs object with two integer arrays nums1 and nums2. void add(int index, int val) Adds val to nums2[index], i.e., apply nums2[index] += val. int count(int tot) Returns the number of pairs (i, j) such that nums1[i] + nums2[j] == tot.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map · Design
["FindSumPairs","count","add","count","count","add","add","count"] [[[1,1,2,2,2,3],[1,4,5,2,5,4]],[7],[3,2],[8],[4],[0,1],[1,1],[7]]
count-number-of-pairs-with-absolute-difference-k)number-of-distinct-averages)count-the-number-of-fair-pairs)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1865: Finding Pairs With a Certain Sum
class FindSumPairs {
private int[] nums1;
private int[] nums2;
private Map<Integer, Integer> cnt = new HashMap<>();
public FindSumPairs(int[] nums1, int[] nums2) {
this.nums1 = nums1;
this.nums2 = nums2;
for (int x : nums2) {
cnt.merge(x, 1, Integer::sum);
}
}
public void add(int index, int val) {
cnt.merge(nums2[index], -1, Integer::sum);
nums2[index] += val;
cnt.merge(nums2[index], 1, Integer::sum);
}
public int count(int tot) {
int ans = 0;
for (int x : nums1) {
ans += cnt.getOrDefault(tot - x, 0);
}
return ans;
}
}
/**
* Your FindSumPairs object will be instantiated and called as such:
* FindSumPairs obj = new FindSumPairs(nums1, nums2);
* obj.add(index,val);
* int param_2 = obj.count(tot);
*/
// Accepted solution for LeetCode #1865: Finding Pairs With a Certain Sum
type FindSumPairs struct {
nums1 []int
nums2 []int
cnt map[int]int
}
func Constructor(nums1 []int, nums2 []int) FindSumPairs {
cnt := map[int]int{}
for _, x := range nums2 {
cnt[x]++
}
return FindSumPairs{nums1, nums2, cnt}
}
func (this *FindSumPairs) Add(index int, val int) {
this.cnt[this.nums2[index]]--
this.nums2[index] += val
this.cnt[this.nums2[index]]++
}
func (this *FindSumPairs) Count(tot int) (ans int) {
for _, x := range this.nums1 {
ans += this.cnt[tot-x]
}
return
}
/**
* Your FindSumPairs object will be instantiated and called as such:
* obj := Constructor(nums1, nums2);
* obj.Add(index,val);
* param_2 := obj.Count(tot);
*/
# Accepted solution for LeetCode #1865: Finding Pairs With a Certain Sum
class FindSumPairs:
def __init__(self, nums1: List[int], nums2: List[int]):
self.cnt = Counter(nums2)
self.nums1 = nums1
self.nums2 = nums2
def add(self, index: int, val: int) -> None:
self.cnt[self.nums2[index]] -= 1
self.nums2[index] += val
self.cnt[self.nums2[index]] += 1
def count(self, tot: int) -> int:
return sum(self.cnt[tot - x] for x in self.nums1)
# Your FindSumPairs object will be instantiated and called as such:
# obj = FindSumPairs(nums1, nums2)
# obj.add(index,val)
# param_2 = obj.count(tot)
// Accepted solution for LeetCode #1865: Finding Pairs With a Certain Sum
use std::collections::HashMap;
struct FindSumPairs {
nums1: Vec<i32>,
nums2: Vec<i32>,
cnt: HashMap<i32, i32>,
}
impl FindSumPairs {
fn new(nums1: Vec<i32>, nums2: Vec<i32>) -> Self {
let mut cnt = HashMap::new();
for &x in &nums2 {
*cnt.entry(x).or_insert(0) += 1;
}
Self { nums1, nums2, cnt }
}
fn add(&mut self, index: i32, val: i32) {
let i = index as usize;
let old_val = self.nums2[i];
*self.cnt.entry(old_val).or_insert(0) -= 1;
if self.cnt[&old_val] == 0 {
self.cnt.remove(&old_val);
}
self.nums2[i] += val;
let new_val = self.nums2[i];
*self.cnt.entry(new_val).or_insert(0) += 1;
}
fn count(&self, tot: i32) -> i32 {
let mut ans = 0;
for &x in &self.nums1 {
let target = tot - x;
if let Some(&c) = self.cnt.get(&target) {
ans += c;
}
}
ans
}
}
// Accepted solution for LeetCode #1865: Finding Pairs With a Certain Sum
class FindSumPairs {
private nums1: number[];
private nums2: number[];
private cnt: Map<number, number>;
constructor(nums1: number[], nums2: number[]) {
this.nums1 = nums1;
this.nums2 = nums2;
this.cnt = new Map();
for (const x of nums2) {
this.cnt.set(x, (this.cnt.get(x) || 0) + 1);
}
}
add(index: number, val: number): void {
const old = this.nums2[index];
this.cnt.set(old, this.cnt.get(old)! - 1);
this.nums2[index] += val;
const now = this.nums2[index];
this.cnt.set(now, (this.cnt.get(now) || 0) + 1);
}
count(tot: number): number {
return this.nums1.reduce((acc, x) => acc + (this.cnt.get(tot - x) || 0), 0);
}
}
/**
* Your FindSumPairs object will be instantiated and called as such:
* var obj = new FindSumPairs(nums1, nums2)
* obj.add(index,val)
* var param_2 = obj.count(tot)
*/
Use this to step through a reusable interview workflow for this problem.
Use a simple list or array for storage. Each operation (get, put, remove) requires a linear scan to find the target element — O(n) per operation. Space is O(n) to store the data. The linear search makes this impractical for frequent operations.
Design problems target O(1) amortized per operation by combining data structures (hash map + doubly-linked list for LRU, stack + min-tracking for MinStack). Space is always at least O(n) to store the data. The challenge is achieving constant-time operations through clever structure composition.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.