149
149
150
150
时间复杂度 $O(n^2)$,空间复杂度 $O(C)$。其中 $n$ 是字符串 $word$ 的长度,而 $C$ 是字符集的大小,本题中 $C=26$。
151
151
152
+ ** 方法二:哈希表 + 前缀和 + 枚举**
153
+
154
+ 与方法一类似,我们先用一个哈希表或数组 $mp$ 记录每个字母对应的数字。
155
+
156
+ 如果一个整数子数组的数字之和能被它的长度整除,那么这个子数组的平均值一定是一个整数。而由于子数组中每个元素的数字都在 $[ 1, 9] $ 范围内,因此子数组的平均值只能是 $1, 2, \cdots, 9$ 中的一个。
157
+
158
+ 我们可以枚举子数组的平均值 $i$,如果一个子数组的元素和能被 $i$ 整除,假设子数组为 $a_1, a_2, \cdots, a_k$,那么 $a_1 + a_2 + \cdots + a_k = i \times k$,即 $(a_1 - i) + (a_2 - i) + \cdots + (a_k - i) = 0$。如果我们把 $a_k - i$ 视为一个新的元素 $b_k$,那么原来的子数组就变成了 $b_1, b_2, \cdots, b_k$,其中 $b_1 + b_2 + \cdots + b_k = 0$。我们只需要求出新的数组中,有多少个子数组的元素和为 $0$ 即可,这可以用“哈希表”结合“前缀和”来实现。
159
+
160
+ 时间复杂度 $O(10 \times n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $word$ 的长度。
161
+
152
162
<!-- tabs:start -->
153
163
154
164
### ** Python3**
@@ -173,6 +183,26 @@ class Solution:
173
183
return ans
174
184
```
175
185
186
+ ``` python
187
+ class Solution :
188
+ def countDivisibleSubstrings (self , word : str ) -> int :
189
+ d = [" ab" , " cde" , " fgh" , " ijk" , " lmn" , " opq" , " rst" , " uvw" , " xyz" ]
190
+ mp = {}
191
+ for i, s in enumerate (d, 1 ):
192
+ for c in s:
193
+ mp[c] = i
194
+ ans = 0
195
+ for i in range (1 , 10 ):
196
+ cnt = defaultdict(int )
197
+ cnt[0 ] = 1
198
+ s = 0
199
+ for c in word:
200
+ s += mp[c] - i
201
+ ans += cnt[s]
202
+ cnt[s] += 1
203
+ return ans
204
+ ```
205
+
176
206
### ** Java**
177
207
178
208
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -201,6 +231,33 @@ class Solution {
201
231
}
202
232
```
203
233
234
+ ``` java
235
+ class Solution {
236
+ public int countDivisibleSubstrings (String word ) {
237
+ String [] d = {" ab" , " cde" , " fgh" , " ijk" , " lmn" , " opq" , " rst" , " uvw" , " xyz" };
238
+ int [] mp = new int [26 ];
239
+ for (int i = 0 ; i < d. length; ++ i) {
240
+ for (char c : d[i]. toCharArray()) {
241
+ mp[c - ' a' ] = i + 1 ;
242
+ }
243
+ }
244
+ int ans = 0 ;
245
+ char [] cs = word. toCharArray();
246
+ for (int i = 1 ; i < 10 ; ++ i) {
247
+ Map<Integer , Integer > cnt = new HashMap<> ();
248
+ cnt. put(0 , 1 );
249
+ int s = 0 ;
250
+ for (char c : cs) {
251
+ s += mp[c - ' a' ] - i;
252
+ ans += cnt. getOrDefault(s, 0 );
253
+ cnt. merge(s, 1 , Integer :: sum);
254
+ }
255
+ }
256
+ return ans;
257
+ }
258
+ }
259
+ ```
260
+
204
261
### ** C++**
205
262
206
263
``` cpp
@@ -228,6 +285,31 @@ public:
228
285
};
229
286
```
230
287
288
+ ```cpp
289
+ class Solution {
290
+ public:
291
+ int countDivisibleSubstrings(string word) {
292
+ string d[9] = {"ab", "cde", "fgh", "ijk", "lmn", "opq", "rst", "uvw", "xyz"};
293
+ int mp[26]{};
294
+ for (int i = 0; i < 9; ++i) {
295
+ for (char& c : d[i]) {
296
+ mp[c - 'a'] = i + 1;
297
+ }
298
+ }
299
+ int ans = 0;
300
+ for (int i = 1; i < 10; ++i) {
301
+ unordered_map<int, int> cnt{{0, 1}};
302
+ int s = 0;
303
+ for (char& c : word) {
304
+ s += mp[c - 'a'] - i;
305
+ ans += cnt[s]++;
306
+ }
307
+ }
308
+ return ans;
309
+ }
310
+ };
311
+ ```
312
+
231
313
### ** Go**
232
314
233
315
``` go
@@ -253,6 +335,28 @@ func countDivisibleSubstrings(word string) (ans int) {
253
335
}
254
336
```
255
337
338
+ ``` go
339
+ func countDivisibleSubstrings (word string ) (ans int ) {
340
+ d := []string {" ab" , " cde" , " fgh" , " ijk" , " lmn" , " opq" , " rst" , " uvw" , " xyz" }
341
+ mp := [26 ]int {}
342
+ for i , s := range d {
343
+ for _ , c := range s {
344
+ mp[c-' a' ] = i + 1
345
+ }
346
+ }
347
+ for i := 0 ; i < 10 ; i++ {
348
+ cnt := map [int ]int {0 : 1 }
349
+ s := 0
350
+ for _ , c := range word {
351
+ s += mp[c-' a' ] - i
352
+ ans += cnt[s]
353
+ cnt[s]++
354
+ }
355
+ }
356
+ return
357
+ }
358
+ ```
359
+
256
360
### ** TypeScript**
257
361
258
362
``` ts
@@ -279,6 +383,31 @@ function countDivisibleSubstrings(word: string): number {
279
383
}
280
384
```
281
385
386
+ ``` ts
387
+ function countDivisibleSubstrings(word : string ): number {
388
+ const d = [' ab' , ' cde' , ' fgh' , ' ijk' , ' lmn' , ' opq' , ' rst' , ' uvw' , ' xyz' ];
389
+ const mp: number [] = Array (26 ).fill (0 );
390
+
391
+ d .forEach ((s , i ) => {
392
+ for (const c of s ) {
393
+ mp [c .charCodeAt (0 ) - ' a' .charCodeAt (0 )] = i + 1 ;
394
+ }
395
+ });
396
+
397
+ let ans = 0 ;
398
+ for (let i = 0 ; i < 10 ; i ++ ) {
399
+ const cnt: { [key : number ]: number } = { 0 : 1 };
400
+ let s = 0 ;
401
+ for (const c of word ) {
402
+ s += mp [c .charCodeAt (0 ) - ' a' .charCodeAt (0 )] - i ;
403
+ ans += cnt [s ] || 0 ;
404
+ cnt [s ] = (cnt [s ] || 0 ) + 1 ;
405
+ }
406
+ }
407
+ return ans ;
408
+ }
409
+ ```
410
+
282
411
### ** Rust**
283
412
284
413
``` rust
@@ -310,6 +439,34 @@ impl Solution {
310
439
}
311
440
```
312
441
442
+ ``` rust
443
+ use std :: collections :: HashMap ;
444
+
445
+ impl Solution {
446
+ pub fn count_divisible_substrings (word : String ) -> i32 {
447
+ let d = vec! [" ab" , " cde" , " fgh" , " ijk" , " lmn" , " opq" , " rst" , " uvw" , " xyz" ];
448
+ let mut mp : Vec <usize > = vec! [0 ; 26 ];
449
+ for (i , s ) in d . iter (). enumerate () {
450
+ for c in s . chars () {
451
+ mp [(c as usize ) - ('a' as usize )] = i + 1 ;
452
+ }
453
+ }
454
+ let mut ans = 0 ;
455
+ for i in 0 .. 10 {
456
+ let mut cnt : HashMap <i32 , i32 > = HashMap :: new ();
457
+ cnt . insert (0 , 1 );
458
+ let mut s = 0 ;
459
+ for c in word . chars () {
460
+ s += (mp [(c as usize ) - ('a' as usize )] - i ) as i32 ;
461
+ ans += cnt . get (& s ). cloned (). unwrap_or (0 );
462
+ * cnt . entry (s ). or_insert (0 ) += 1 ;
463
+ }
464
+ }
465
+ ans
466
+ }
467
+ }
468
+ ```
469
+
313
470
### ** ...**
314
471
315
472
```
0 commit comments