@@ -80,33 +80,35 @@ findSumPairs.count(7); // 返回 11 ;下标对 (2,1), (2,2), (2,4), (3,1), (3
80
80
81
81
### 方法一:哈希表
82
82
83
- 我们可以用哈希表 ` cnt ` 统计数组 ` nums2 ` 中每个数字出现的次数 。
83
+ 我们注意到,数组 $\textit{nums1}$ 的长度不超过 ${10}^3$,数组 $\textit{ nums2}$ 的长度达到 ${10}^5$,因此,如果直接暴力枚举所有下标对 $(i, j)$,计算 $\textit{nums1} [ i ] + \textit{nums2} [ j ] $ 是否等于指定值 $\textit{tot}$,那么会超出时间限制 。
84
84
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 ] $ 的值之和即可 。
86
86
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$ 。
88
88
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}$ 方法的次数。
90
92
91
93
<!-- tabs:start -->
92
94
93
95
#### Python3
94
96
95
97
``` python
96
98
class FindSumPairs :
99
+
97
100
def __init__ (self , nums1 : List[int ], nums2 : List[int ]):
101
+ self .cnt = Counter(nums2)
98
102
self .nums1 = nums1
99
103
self .nums2 = nums2
100
- self .cnt = Counter(nums2)
101
104
102
105
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
106
107
self .nums2[index] += val
108
+ self .cnt[self .nums2[index]] += 1
107
109
108
110
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)
110
112
111
113
112
114
# Your FindSumPairs object will be instantiated and called as such:
@@ -126,22 +128,21 @@ class FindSumPairs {
126
128
public FindSumPairs (int [] nums1 , int [] nums2 ) {
127
129
this . nums1 = nums1;
128
130
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 );
131
133
}
132
134
}
133
135
134
136
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);
138
138
nums2[index] += val;
139
+ cnt. merge(nums2[index], 1 , Integer :: sum);
139
140
}
140
141
141
142
public int count (int tot ) {
142
143
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 );
145
146
}
146
147
return ans;
147
148
}
@@ -163,22 +164,21 @@ public:
163
164
FindSumPairs(vector<int >& nums1, vector<int >& nums2) {
164
165
this->nums1 = nums1;
165
166
this->nums2 = nums2;
166
- for (int& v : nums2) {
167
- ++cnt[ v ] ;
167
+ for (int x : nums2) {
168
+ ++cnt[ x ] ;
168
169
}
169
170
}
170
171
171
172
void add(int index, int val) {
172
- int old = nums2[index];
173
- --cnt[old];
174
- ++cnt[old + val];
173
+ --cnt[nums2[index]];
175
174
nums2[index] += val;
175
+ ++cnt[nums2[index]];
176
176
}
177
177
178
178
int count (int tot) {
179
179
int ans = 0;
180
- for (int& v : nums1) {
181
- ans += cnt[ tot - v ] ;
180
+ for (int x : nums1) {
181
+ ans += cnt[ tot - x ] ;
182
182
}
183
183
return ans;
184
184
}
@@ -208,22 +208,21 @@ type FindSumPairs struct {
208
208
209
209
func Constructor(nums1 []int, nums2 []int) FindSumPairs {
210
210
cnt := map[int]int{}
211
- for _, v := range nums2 {
212
- cnt[v ]++
211
+ for _, x := range nums2 {
212
+ cnt[x ]++
213
213
}
214
214
return FindSumPairs{nums1, nums2, cnt}
215
215
}
216
216
217
217
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]]--
221
219
this.nums2[index] += val
220
+ this.cnt[this.nums2[index]]++
222
221
}
223
222
224
223
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 ]
227
226
}
228
227
return
229
228
}
@@ -236,6 +235,147 @@ func (this *FindSumPairs) Count(tot int) (ans int) {
236
235
*/
237
236
```
238
237
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
+
239
379
<!-- tabs:end -->
240
380
241
381
<!-- solution:end -->
0 commit comments