1865. Finding Pairs With a Certain Sum
Problem Description
You are provided with two integer arrays, nums1
and nums2
, and the goal is to create a data structure that supports two types of queries. Firstly, you should be able to add a positive integer to an element at a given index in nums2
. Secondly, you need to count the number of pairs (i, j)
where the sum of nums1[i]
and nums2[j]
is equal to a specified value (tot
). The pairs should only be considered if i
and j
are valid indexes within nums1
and nums2
, respectively.
To accomplish the task, you should implement a class FindSumPairs
with the following methods:
FindSumPairs(int[] nums1, int[] nums2)
: a constructor that initializes the object with the two integer arrays,nums1
andnums2
.add(int index, int val)
: a method that adds the integerval
to the element atindex
innums2
.count(int tot)
: a method that returns the number of pairs(i, j)
wherenums1[i] + nums2[j]
equals the integertot
.
Intuition
The intuitive approach to solving this problem involves efficient data retrieval and update methods. If we were to perform a brute force approach for the count operation, we would iterate through all possible (i, j)
pairs to find their sum and compare with tot
, which would result in a time-consuming process, especially with large arrays.
A better way is to use a hash table to keep track of the frequency of each number in nums2
. This allows us to quickly calculate how many times a certain number that can be added to elements of nums1
appears in nums2
to reach the required sum (tot
).
Here's the intuition for the methods:
- The constructor initializes the object and also creates a counter (
Counter
fromcollections
in Python) that maps each number innums2
to its frequency. - The
add
method updates the specific element innums2
and adjusts the counter correspondingly. If a number's frequency changes (because it's being increased byval
), we decrease the count of the old number and increase the count for the new, updated number. - The
count
method calculates the required pairs by traversing throughnums1
and checking if the complement to reachtot
(calculated astot - nums1[i]
) exists in the hash table (counter fornums2
). The sum of all the frequencies of these complements gives us the total number of valid pairs that meet the condition.
Solution Approach
The implementation of the FindSumPairs
class makes use of hash tables to store elements and their frequencies from nums2
. This is essentially a mapping from each unique integer in nums2
to the number of times it appears. The Python Counter
class from the collections
module is used here for this purpose as it automatically counts the frequency of items in a list.
Here's the breakdown of the implementation:
The __init__
function of the FindSumPairs
class initializes two properties, nums1
and nums2
, with the corresponding input arrays. Additionally, a Counter
object named cnt
is created to store the frequency count of elements in nums2
.
def __init__(self, nums1: List[int], nums2: List[int]):
self.nums1 = nums1
self.nums2 = nums2
self.cnt = Counter(nums2)
The add
function takes in an index
and a value val
to add to nums2
at the specified index. Before updating nums2[index]
with the new value, it decreases the count of the old value in cnt
. Then, it increases the count of nums2[index]
plus val
. After updating the cnt
, nums2
is updated with the new value.
def add(self, index: int, val: int) -> None:
old = self.nums2[index]
self.cnt[old] -= 1
if self.cnt[old] == 0:
del self.cnt[old] # Remove the entry from the counter if the frequency is zero
self.cnt[old + val] += 1
self.nums2[index] += val
The count
function takes in a value tot
and returns the number of pairs (i, j)
where nums1[i] + nums2[j] == tot
. To do this, it sums up the counts of tot - nums1[i]
in cnt
for each element i
in nums1
. In other words, for every number in nums1
, it calculates the complement (the number that needs to be added to it in order to reach tot
) and uses this to get the frequency of such complements from the Counter
.
def count(self, tot: int) -> int:
return sum(self.cnt[tot - v] for v in self.nums1)
By utilizing the Counter
, the class is able to execute the count
function in O(n) time relative to the size of nums1
, as it only has to iterate over nums1
and can retrieve the complement counts in constant time from the hash table. This is significantly more efficient than attempting to calculate the pairs through nested loops, which would be O(n * m) where n and m are the sizes of nums1
and nums2
.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's step through the problem using a small example to illustrate the solution approach.
Suppose nums1
is [1, 2, 3]
and nums2
is [1, 4, 5, 2]
, and we are interested in finding pairs whose sum equals tot = 5
.
Upon class initialization:
nums1
remains[1, 2, 3]
.nums2
remains[1, 4, 5, 2]
.- A
Counter
is created fromnums2
, resulting in{1: 1, 4: 1, 5: 1, 2: 1}
.
Now, let's say we perform an add
operation – add(2, 2)
– which adds 2
to the element at index 2
in nums2
.
- The old value at
nums2[2]
is5
, so the counter for5
is decreased from1
to0
and consequently removed since its count is now zero. - The value at
nums2[2]
is updated to7
(5 + 2
), so the counter for7
is increased from0
to1
. - Now
nums2
becomes[1, 4, 7, 2]
, and theCounter
reflects{1: 1, 4: 1, 7: 1, 2: 1}
.
Next, we perform a count
operation – count(5)
to find pairs summing up to 5
.
- We iterate through
nums1
, looking for values that, when added to values fromnums2
, yield5
. - For
nums1[0] = 1
, we findtot - nums1[0] = 5 - 1 = 4
;cnt[4]
equals1
indicating a pair (1, 4). - For
nums1[1] = 2
,tot - nums1[1] = 5 - 2 = 3
;cnt[3]
equals0
indicating no valid pair exists with the second element2
. - For
nums1[2] = 3
,tot - nums1[2] = 5 - 3 = 2
;cnt[2]
equals1
indicating a pair (3, 2). - Sum up the counts of valid pairs for all elements in
nums1
, giving uscnt[4] + cnt[3] + cnt[2] = 1 + 0 + 1 = 2
.
Therefore, the count(5)
operation tells us there are 2 valid pairs (1, 4)
and (3, 2)
whose sum equals 5
.
This example demonstrates the efficiency of the approach using a Counter
to avoid iterating over nums2
each time we call count
. Instead, we make use of the precomputed frequencies to quickly tally the number of pairs that sum up to tot
.
Solution Implementation
1from collections import Counter
2from typing import List
3
4class FindSumPairs:
5 def __init__(self, nums1: List[int], nums2: List[int]):
6 # Store the two lists and create a counter for nums2 to keep track of occurrences
7 self.nums1 = nums1
8 self.nums2 = nums2
9 self.counts = Counter(nums2) # using 'counts' in place of 'cnt' for readability
10
11 def add(self, index: int, val: int) -> None:
12 # Function to update the value at a given index in nums2 and adjust the counter
13 old_val = self.nums2[index]
14 # Decrease the count for the old value
15 self.counts[old_val] -= 1
16 # If the old value count drops to 0, remove it from the counter to keep it clean
17 if self.counts[old_val] == 0:
18 del self.counts[old_val]
19 # Update the value in nums2
20 self.nums2[index] += val
21 # Increase the count for the new value
22 self.counts[self.nums2[index]] += 1
23
24 def count(self, total: int) -> int:
25 # Function to find the number of pairs from nums1 and nums2 that sum up to 'total'
26 result = 0
27 # Iterate over values in nums1 and check if (total - value) exists in nums2's counter
28 for value in self.nums1:
29 result += self.counts[total - value]
30 return result
31
32# The class FindSumPairs can be used as follows:
33# obj = FindSumPairs(nums1, nums2)
34# obj.add(index, val)
35# pair_count = obj.count(total)
36
1import java.util.HashMap;
2import java.util.Map;
3
4// Class to find count of pairs from two arrays that sum up to a given value
5class FindSumPairs {
6 // Arrays to store the two input integer arrays
7 private int[] nums1;
8 private int[] nums2;
9 // Map to keep the frequency count of elements in the second array
10 private Map<Integer, Integer> frequencyMap = new HashMap<>();
11
12 // Constructor initializes the class with two integer arrays
13 public FindSumPairs(int[] nums1, int[] nums2) {
14 this.nums1 = nums1;
15 this.nums2 = nums2;
16
17 // Populating the frequency map with the count of each number in nums2
18 for (int value : nums2) {
19 frequencyMap.put(value, frequencyMap.getOrDefault(value, 0) + 1);
20 }
21 }
22
23 // Method that increments an element of nums2 at a given index by a given value
24 public void add(int index, int value) {
25 // Obtain the original value at the given index in nums2
26 int originalValue = nums2[index];
27 // Decrement the frequency of the original value in the frequency map
28 frequencyMap.put(originalValue, frequencyMap.get(originalValue) - 1);
29 // Increment the original value by the given value and update in nums2
30 nums2[index] += value;
31 // Increment the frequency of the new value in the frequency map
32 frequencyMap.put(nums2[index], frequencyMap.getOrDefault(nums2[index], 0) + 1);
33 }
34
35 // Method that counts the pairs across nums1 and nums2 that sum up to a given total
36 public int count(int total) {
37 int count = 0;
38 // Iterate through each value in nums1
39 for (int value : nums1) {
40 // For the current value in nums1, check if there's a complement in nums2 that sums up to total
41 count += frequencyMap.getOrDefault(total - value, 0);
42 }
43 // Return the count of such pairs
44 return count;
45 }
46}
47
48/*
49 * The usage of the FindSumPairs class:
50 *
51 * FindSumPairs obj = new FindSumPairs(nums1, nums2);
52 * obj.add(index, value);
53 * int result = obj.count(total);
54 */
55
1#include <vector>
2#include <unordered_map>
3using namespace std;
4
5class FindSumPairs {
6public:
7 // Constructor initializes the object with two integer vectors
8 FindSumPairs(vector<int>& nums1, vector<int>& nums2) {
9 this->nums1 = nums1; // Assign the first vector to the class member
10 this->nums2 = nums2; // Assign the second vector to the class member
11
12 // Populate the count map with the frequency of each number in nums2
13 for (int value : nums2) {
14 ++countMap[value];
15 }
16 }
17
18 // Function to add a value to an element in nums2 and update the count map
19 void add(int index, int value) {
20 int oldValue = nums2[index]; // Retrieve the old value from nums2 at the given index
21 --countMap[oldValue]; // Decrease the count of the old value in the map
22 ++countMap[oldValue + value]; // Increase the count of the new value in the map
23 nums2[index] += value; // Update the value in nums2 by adding the given value
24 }
25
26 // Function to count the pairs with the given sum 'total'
27 int count(int total) {
28 int pairsCount = 0; // Initialize the count of valid pairs
29
30 // Iterate through elements in nums1 and calculate the complement
31 for (int value : nums1) {
32 pairsCount += countMap[total - value]; // Add the count of the complement from the map to the pairs count
33 }
34
35 return pairsCount; // Return the total count of valid pairs
36 }
37
38private:
39 vector<int> nums1; // First input vector
40 vector<int> nums2; // Second input vector
41 unordered_map<int, int> countMap; // Map to store the frequency of each number in nums2
42};
43
44/**
45 * The FindSumPairs class is instantiated and used as follows:
46 * FindSumPairs* obj = new FindSumPairs(nums1, nums2); // Create a new FindSumPairs object
47 * obj->add(index, value); // Add a value to the element at the given index in nums2
48 * int result = obj->count(total); // Count the pairs that add up to a total
49 * delete obj; // Clean up the object when done (important for memory management)
50 */
51
1// The original C++ includes and namespace declaration are not needed in TypeScript.
2
3// Global variables for the two number arrays and the count map
4let nums1: number[];
5let nums2: number[];
6let countMap: { [key: number]: number } = {};
7
8// Function to initialize the object with two integer arrays
9function initialize(nums1Input: number[], nums2Input: number[]): void {
10 nums1 = nums1Input; // Assign the first array to the global variable
11 nums2 = nums2Input; // Assign the second array to the global variable
12
13 // Populate the count map with the frequency of each number in nums2
14 countMap = {}; // Reset count map
15 nums2.forEach((value) => {
16 if (countMap[value] === undefined) {
17 countMap[value] = 0;
18 }
19 countMap[value]++;
20 });
21}
22
23// Function to add a value to an element in nums2 and update the count map
24function add(index: number, value: number): void {
25 const oldValue = nums2[index]; // Retrieve the old value from nums2 at the given index
26 countMap[oldValue]--; // Decrease the count of the old value in the map
27 const newValue = oldValue + value;
28 if (countMap[newValue] === undefined) {
29 countMap[newValue] = 0;
30 }
31 countMap[newValue]++; // Increase the count of the new value in the map
32 nums2[index] = newValue; // Update the value in nums2 by adding the given value
33}
34
35// Function to count the pairs with the given sum 'total'
36function count(total: number): number {
37 let pairsCount = 0; // Initialize the count of valid pairs
38
39 // Iterate through elements in nums1 and calculate the complement
40 nums1.forEach((value) => {
41 const complement = total - value;
42 pairsCount += countMap[complement] ?? 0; // Add the count of the complement from the map to the pairs count
43 });
44
45 return pairsCount; // Return the total count of valid pairs
46}
47
48// Example usage:
49/*
50initialize([1, 2, 3, 4], [2, 3, 4, 5]);
51add(3, 2); // Now nums2 is [2, 3, 4, 7]
52const result = count(8); // There are 2 pairs that add up to 8: (1,7) and (4,4)
53console.log(result); // Outputs: 2
54*/
55
Time and Space Complexity
Time Complexity
-
__init__(self, nums1: List[int], nums2: List[int])
: The constructor initializes two listsnums1
andnums2
. It also counts the elements ofnums2
usingCounter
which takesO(n)
time wheren
is the length ofnums2
. -
add(self, index: int, val: int) -> None
: This method updates an element innums2
and modifies the count of the old and the new value incnt
. The update operation and the changes in the counter have a constant time complexityO(1)
since dictionary (counter) operations in Python have an average-case complexity ofO(1)
. -
count(self, tot: int) -> int
: The count method iterates overnums1
and for each elementv
innums1
, it accesses the countercnt
to find the count of(tot - v)
. Ifnums1
hasm
elements, the time complexity isO(m)
since each lookup in the counter isO(1)
on average.
Space Complexity
-
__init__(self, nums1: List[int], nums2: List[int])
: Apart from the input listsnums1
andnums2
, a countercnt
is created to store the frequency of each element innums2
. The space complexity isO(n)
wheren
is the number of unique elements innums2
. -
add(self, index: int, val: int) -> None
: This method uses no extra space and thus has a space complexity ofO(1)
. -
count(self, tot: int) -> int
: This method does not use extra space apart from a few variables for its operation, hence the space complexity isO(1)
.
Overall, the space complexity of the FindSumPairs
class is determined by the space required for storing the input lists and the counter, which is O(n)
where n
is the size of nums2
and the number of unique elements it contains.
Learn more about how to find time and space complexity quickly using problem constraints.
How does merge sort divide the problem into subproblems?
Recommended Readings
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!