Skip to content

Commit 9c092cf

Browse files
authored
feat: add solutions to lc problem: No.1865 (#4040)
No.1865.Finding Pairs With a Certain Sum
1 parent 89b48f7 commit 9c092cf

File tree

9 files changed

+496
-86
lines changed

9 files changed

+496
-86
lines changed

solution/1800-1899/1865.Finding Pairs With a Certain Sum/README.md

+170-30
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,35 @@ findSumPairs.count(7); // 返回 11 ;下标对 (2,1), (2,2), (2,4), (3,1), (3
8080

8181
### 方法一:哈希表
8282

83-
我们可以用哈希表 `cnt` 统计数组 `nums2` 中每个数字出现的次数
83+
我们注意到,数组 $\textit{nums1}$ 的长度不超过 ${10}^3$,数组 $\textit{nums2}$ 的长度达到 ${10}^5$,因此,如果直接暴力枚举所有下标对 $(i, j)$,计算 $\textit{nums1}[i] + \textit{nums2}[j]$ 是否等于指定值 $\textit{tot}$,那么会超出时间限制
8484

85-
对于 `add` 操作,我们需要更新哈希表中 `nums2[index]` 的值,即 `cnt[nums2[index]] -= 1`,然后更新 `nums2[index] += val`,最后更新哈希表中 `nums2[index]` 的值,即 `cnt[nums2[index]] += 1`
85+
能否只枚举长度较短的数组 $\textit{nums1}$ 呢?答案是可以的。我们用一个哈希表 $\textit{cnt}$ 统计数组 $\textit{nums2}$ 中每个元素出现的次数,然后枚举数组 $\textit{nums1}$ 中的每个元素 $x$,计算 $\textit{cnt}[\textit{tot} - x]$ 的值之和即可
8686

87-
对于 `count` 操作,我们遍历数组 `nums1`,对于每个数字 `v`,我们需要统计满足 `tot - v` 的数字出现的次数,即 `cnt[tot - v]`,然后将其累加到答案中
87+
在调用 $\text{add}$ 方法时,我们需要先将 $\textit{nums2}[index]$ 对应的值从 $\textit{cnt}$ 中减去 $1$,然后将 $\textit{nums2}[index]$ 的值加上 $\textit{val}$,最后将 $\textit{nums2}[index]$ 对应的值加上 $1$
8888

89-
时间复杂度:对于 `add` 操作,时间复杂度为 $O(1)$,对于 `count` 操作,时间复杂度为 $O(n)$,其中 $n$ 为数组 `nums1` 的长度。空间复杂度 $O(m)$,其中 $m$ 为数组 `nums2` 的长度。
89+
在调用 $\text{count}$ 方法时,我们只需要遍历数组 $\textit{nums1}$,对于每个元素 $x$,计算 $\textit{cnt}[\textit{tot} - x]$ 的值之和即可。
90+
91+
时间复杂度 $O(n \times q)$,空间复杂度 $O(m)$。其中 $n$ 和 $m$ 分别是数组 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度,而 $q$ 是调用 $\text{count}$ 方法的次数。
9092

9193
<!-- tabs:start -->
9294

9395
#### Python3
9496

9597
```python
9698
class FindSumPairs:
99+
97100
def __init__(self, nums1: List[int], nums2: List[int]):
101+
self.cnt = Counter(nums2)
98102
self.nums1 = nums1
99103
self.nums2 = nums2
100-
self.cnt = Counter(nums2)
101104

102105
def add(self, index: int, val: int) -> None:
103-
old = self.nums2[index]
104-
self.cnt[old] -= 1
105-
self.cnt[old + val] += 1
106+
self.cnt[self.nums2[index]] -= 1
106107
self.nums2[index] += val
108+
self.cnt[self.nums2[index]] += 1
107109

108110
def count(self, tot: int) -> int:
109-
return sum(self.cnt[tot - v] for v in self.nums1)
111+
return sum(self.cnt[tot - x] for x in self.nums1)
110112

111113

112114
# Your FindSumPairs object will be instantiated and called as such:
@@ -126,22 +128,21 @@ class FindSumPairs {
126128
public FindSumPairs(int[] nums1, int[] nums2) {
127129
this.nums1 = nums1;
128130
this.nums2 = nums2;
129-
for (int v : nums2) {
130-
cnt.put(v, cnt.getOrDefault(v, 0) + 1);
131+
for (int x : nums2) {
132+
cnt.merge(x, 1, Integer::sum);
131133
}
132134
}
133135

134136
public void add(int index, int val) {
135-
int old = nums2[index];
136-
cnt.put(old, cnt.get(old) - 1);
137-
cnt.put(old + val, cnt.getOrDefault(old + val, 0) + 1);
137+
cnt.merge(nums2[index], -1, Integer::sum);
138138
nums2[index] += val;
139+
cnt.merge(nums2[index], 1, Integer::sum);
139140
}
140141

141142
public int count(int tot) {
142143
int ans = 0;
143-
for (int v : nums1) {
144-
ans += cnt.getOrDefault(tot - v, 0);
144+
for (int x : nums1) {
145+
ans += cnt.getOrDefault(tot - x, 0);
145146
}
146147
return ans;
147148
}
@@ -163,22 +164,21 @@ public:
163164
FindSumPairs(vector<int>& nums1, vector<int>& nums2) {
164165
this->nums1 = nums1;
165166
this->nums2 = nums2;
166-
for (int& v : nums2) {
167-
++cnt[v];
167+
for (int x : nums2) {
168+
++cnt[x];
168169
}
169170
}
170171

171172
void add(int index, int val) {
172-
int old = nums2[index];
173-
--cnt[old];
174-
++cnt[old + val];
173+
--cnt[nums2[index]];
175174
nums2[index] += val;
175+
++cnt[nums2[index]];
176176
}
177177

178178
int count(int tot) {
179179
int ans = 0;
180-
for (int& v : nums1) {
181-
ans += cnt[tot - v];
180+
for (int x : nums1) {
181+
ans += cnt[tot - x];
182182
}
183183
return ans;
184184
}
@@ -208,22 +208,21 @@ type FindSumPairs struct {
208208
209209
func Constructor(nums1 []int, nums2 []int) FindSumPairs {
210210
cnt := map[int]int{}
211-
for _, v := range nums2 {
212-
cnt[v]++
211+
for _, x := range nums2 {
212+
cnt[x]++
213213
}
214214
return FindSumPairs{nums1, nums2, cnt}
215215
}
216216
217217
func (this *FindSumPairs) Add(index int, val int) {
218-
old := this.nums2[index]
219-
this.cnt[old]--
220-
this.cnt[old+val]++
218+
this.cnt[this.nums2[index]]--
221219
this.nums2[index] += val
220+
this.cnt[this.nums2[index]]++
222221
}
223222
224223
func (this *FindSumPairs) Count(tot int) (ans int) {
225-
for _, v := range this.nums1 {
226-
ans += this.cnt[tot-v]
224+
for _, x := range this.nums1 {
225+
ans += this.cnt[tot-x]
227226
}
228227
return
229228
}
@@ -236,6 +235,147 @@ func (this *FindSumPairs) Count(tot int) (ans int) {
236235
*/
237236
```
238237

238+
#### TypeScript
239+
240+
```ts
241+
class FindSumPairs {
242+
private nums1: number[];
243+
private nums2: number[];
244+
private cnt: Map<number, number>;
245+
246+
constructor(nums1: number[], nums2: number[]) {
247+
this.nums1 = nums1;
248+
this.nums2 = nums2;
249+
this.cnt = new Map();
250+
for (const x of nums2) {
251+
this.cnt.set(x, (this.cnt.get(x) || 0) + 1);
252+
}
253+
}
254+
255+
add(index: number, val: number): void {
256+
const old = this.nums2[index];
257+
this.cnt.set(old, this.cnt.get(old)! - 1);
258+
this.nums2[index] += val;
259+
const now = this.nums2[index];
260+
this.cnt.set(now, (this.cnt.get(now) || 0) + 1);
261+
}
262+
263+
count(tot: number): number {
264+
return this.nums1.reduce((acc, x) => acc + (this.cnt.get(tot - x) || 0), 0);
265+
}
266+
}
267+
268+
/**
269+
* Your FindSumPairs object will be instantiated and called as such:
270+
* var obj = new FindSumPairs(nums1, nums2)
271+
* obj.add(index,val)
272+
* var param_2 = obj.count(tot)
273+
*/
274+
```
275+
276+
#### JavaScript
277+
278+
```js
279+
/**
280+
* @param {number[]} nums1
281+
* @param {number[]} nums2
282+
*/
283+
var FindSumPairs = function (nums1, nums2) {
284+
this.nums1 = nums1;
285+
this.nums2 = nums2;
286+
this.cnt = new Map();
287+
for (const x of nums2) {
288+
this.cnt.set(x, (this.cnt.get(x) || 0) + 1);
289+
}
290+
};
291+
292+
/**
293+
* @param {number} index
294+
* @param {number} val
295+
* @return {void}
296+
*/
297+
FindSumPairs.prototype.add = function (index, val) {
298+
const old = this.nums2[index];
299+
this.cnt.set(old, this.cnt.get(old) - 1);
300+
this.nums2[index] += val;
301+
const now = this.nums2[index];
302+
this.cnt.set(now, (this.cnt.get(now) || 0) + 1);
303+
};
304+
305+
/**
306+
* @param {number} tot
307+
* @return {number}
308+
*/
309+
FindSumPairs.prototype.count = function (tot) {
310+
return this.nums1.reduce((acc, x) => acc + (this.cnt.get(tot - x) || 0), 0);
311+
};
312+
313+
/**
314+
* Your FindSumPairs object will be instantiated and called as such:
315+
* var obj = new FindSumPairs(nums1, nums2)
316+
* obj.add(index,val)
317+
* var param_2 = obj.count(tot)
318+
*/
319+
```
320+
321+
#### C#
322+
323+
```cs
324+
public class FindSumPairs {
325+
private int[] nums1;
326+
private int[] nums2;
327+
private Dictionary<int, int> cnt = new Dictionary<int, int>();
328+
329+
public FindSumPairs(int[] nums1, int[] nums2) {
330+
this.nums1 = nums1;
331+
this.nums2 = nums2;
332+
foreach (int x in nums2) {
333+
if (cnt.ContainsKey(x)) {
334+
cnt[x]++;
335+
} else {
336+
cnt[x] = 1;
337+
}
338+
}
339+
}
340+
341+
public void Add(int index, int val) {
342+
int oldVal = nums2[index];
343+
if (cnt.TryGetValue(oldVal, out int oldCount)) {
344+
if (oldCount == 1) {
345+
cnt.Remove(oldVal);
346+
} else {
347+
cnt[oldVal] = oldCount - 1;
348+
}
349+
}
350+
nums2[index] += val;
351+
int newVal = nums2[index];
352+
if (cnt.TryGetValue(newVal, out int newCount)) {
353+
cnt[newVal] = newCount + 1;
354+
} else {
355+
cnt[newVal] = 1;
356+
}
357+
}
358+
359+
public int Count(int tot) {
360+
int ans = 0;
361+
foreach (int x in nums1) {
362+
int target = tot - x;
363+
if (cnt.TryGetValue(target, out int count)) {
364+
ans += count;
365+
}
366+
}
367+
return ans;
368+
}
369+
}
370+
371+
/**
372+
* Your FindSumPairs object will be instantiated and called as such:
373+
* FindSumPairs obj = new FindSumPairs(nums1, nums2);
374+
* obj.Add(index,val);
375+
* int param_2 = obj.Count(tot);
376+
*/
377+
```
378+
239379
<!-- tabs:end -->
240380

241381
<!-- solution:end -->

0 commit comments

Comments
 (0)