Skip to content

Commit 5b00456

Browse files
authored
feat: add solutions to lc problem: No.2950 (doocs#2062)
No.2950.Number of Divisible Substrings
1 parent 5cba60b commit 5b00456

File tree

8 files changed

+365
-47
lines changed

8 files changed

+365
-47
lines changed

solution/2900-2999/2950.Number of Divisible Substrings/README.md

+157
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@
149149

150150
时间复杂度 $O(n^2)$,空间复杂度 $O(C)$。其中 $n$ 是字符串 $word$ 的长度,而 $C$ 是字符集的大小,本题中 $C=26$。
151151

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+
152162
<!-- tabs:start -->
153163

154164
### **Python3**
@@ -173,6 +183,26 @@ class Solution:
173183
return ans
174184
```
175185

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+
176206
### **Java**
177207

178208
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -201,6 +231,33 @@ class Solution {
201231
}
202232
```
203233

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+
204261
### **C++**
205262

206263
```cpp
@@ -228,6 +285,31 @@ public:
228285
};
229286
```
230287
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+
231313
### **Go**
232314

233315
```go
@@ -253,6 +335,28 @@ func countDivisibleSubstrings(word string) (ans int) {
253335
}
254336
```
255337

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+
256360
### **TypeScript**
257361

258362
```ts
@@ -279,6 +383,31 @@ function countDivisibleSubstrings(word: string): number {
279383
}
280384
```
281385

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+
282411
### **Rust**
283412

284413
```rust
@@ -310,6 +439,34 @@ impl Solution {
310439
}
311440
```
312441

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+
313470
### **...**
314471

315472
```

0 commit comments

Comments
 (0)