Skip to content

Commit 1d15cc5

Browse files
authored
feat: update solutions to lc problems: No.1100,1852 (#2569)
* No.1100.Find K-Length Substrings With No Repeated Characters * No.1852.Distinct Numbers in Each Subarray
1 parent 551577c commit 1d15cc5

File tree

14 files changed

+234
-436
lines changed

14 files changed

+234
-436
lines changed

solution/1100-1199/1100.Find K-Length Substrings With No Repeated Characters/README.md

+72-148
Original file line numberDiff line numberDiff line change
@@ -39,52 +39,52 @@
3939

4040
## 解法
4141

42-
### 方法一:双指针 + 计数器
42+
### 方法一:滑动窗口 + 哈希表
4343

44-
我们观察发现,字符均为小写字母,也即最多有 $26$ 种不同的字符。因此,如果 $k \gt 26$ 或者 $k \gt n$,则无法找到任何长度为 $k$ 且不含重复字符的子串,直接返回 $0$ 即可
44+
我们维护一个长度为 $k$ 的滑动窗口,用一个哈希表 $cnt$ 统计窗口中每个字符的出现次数
4545

46-
接下来,我们用双指针 $j$ 和 $i$ 维护一个滑动窗口,其中 $j$ 是滑动窗口的左端点,$i$ 是滑动窗口的右端点,用一个计数器 $cnt$ 统计滑动窗口中每个字符出现的次数
46+
首先,我们将字符串 $s$ 的前 $k$ 个字符加入哈希表 $cnt$ 中,并判断 $cnt$ 的大小是否等于 $k$,如果等于 $k$,则说明窗口中的字符都不相同,答案 $ans$ 加一
4747

48-
遍历字符串 $s$,每次将 $s[i]$ 加入滑动窗口,即 $cnt[s[i]]++$,如果此时 $cnt[s[i]] \gt 1$ 或者 $i - j + 1 \gt k$,则循环将 $s[j]$ 从滑动窗口中移除,即 $cnt[s[j]]--$,并将 $j$ 右移。如果 $j$ 右移结束后,窗口大小 $i - j + 1$ 恰好等于 $k$,则说明滑动窗口中的字符串是一个符合题意的子串,将结果加一
48+
接下来,我们从 $k$ 开始遍历字符串 $s$,每次将 $s[i]$ 加入哈希表 $cnt$ 中,同时将 $s[i-k]$ 从哈希表 $cnt$ 中减一,如果 $cnt[s[i-k]]$ 减一后等于 $0$,则将 $s[i-k]$ 从哈希表 $cnt$ 中删除。如果此时哈希表 $cnt$ 的大小等于 $k$,则说明窗口中的字符都不相同,答案 $ans$ 加一
4949

50-
遍历结束后,即可得到所有符合题意的子串的个数
50+
最后,返回答案 $ans$ 即可
5151

52-
时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度;而 $C$ 为字符集的大小,本题中 $C = 26$。
52+
时间复杂度 $O(n)$,空间复杂度 $O(\min(k, |\Sigma|))$,其中 $n$ 为字符串 $s$ 的长度;而 $\Sigma$ 为字符集,本题中字符集为小写英文字母,所以 $|\Sigma| = 26$。
5353

5454
<!-- tabs:start -->
5555

5656
```python
5757
class Solution:
5858
def numKLenSubstrNoRepeats(self, s: str, k: int) -> int:
59-
n = len(s)
60-
if k > n or k > 26:
61-
return 0
62-
ans = j = 0
63-
cnt = Counter()
64-
for i, c in enumerate(s):
65-
cnt[c] += 1
66-
while cnt[c] > 1 or i - j + 1 > k:
67-
cnt[s[j]] -= 1
68-
j += 1
69-
ans += i - j + 1 == k
59+
cnt = Counter(s[:k])
60+
ans = int(len(cnt) == k)
61+
for i in range(k, len(s)):
62+
cnt[s[i]] += 1
63+
cnt[s[i - k]] -= 1
64+
if cnt[s[i - k]] == 0:
65+
cnt.pop(s[i - k])
66+
ans += int(len(cnt) == k)
7067
return ans
7168
```
7269

7370
```java
7471
class Solution {
7572
public int numKLenSubstrNoRepeats(String s, int k) {
7673
int n = s.length();
77-
if (k > n || k > 26) {
74+
if (n < k) {
7875
return 0;
7976
}
80-
int[] cnt = new int[128];
81-
int ans = 0;
82-
for (int i = 0, j = 0; i < n; ++i) {
83-
++cnt[s.charAt(i)];
84-
while (cnt[s.charAt(i)] > 1 || i - j + 1 > k) {
85-
cnt[s.charAt(j++)]--;
77+
Map<Character, Integer> cnt = new HashMap<>(k);
78+
for (int i = 0; i < k; ++i) {
79+
cnt.merge(s.charAt(i), 1, Integer::sum);
80+
}
81+
int ans = cnt.size() == k ? 1 : 0;
82+
for (int i = k; i < n; ++i) {
83+
cnt.merge(s.charAt(i), 1, Integer::sum);
84+
if (cnt.merge(s.charAt(i - k), -1, Integer::sum) == 0) {
85+
cnt.remove(s.charAt(i - k));
8686
}
87-
ans += i - j + 1 == k ? 1 : 0;
87+
ans += cnt.size() == k ? 1 : 0;
8888
}
8989
return ans;
9090
}
@@ -96,17 +96,20 @@ class Solution {
9696
public:
9797
int numKLenSubstrNoRepeats(string s, int k) {
9898
int n = s.size();
99-
if (k > n || k > 26) {
99+
if (n < k) {
100100
return 0;
101101
}
102-
int cnt[128]{};
103-
int ans = 0;
104-
for (int i = 0, j = 0; i < n; ++i) {
102+
unordered_map<char, int> cnt;
103+
for (int i = 0; i < k; ++i) {
104+
++cnt[s[i]];
105+
}
106+
int ans = cnt.size() == k;
107+
for (int i = k; i < n; ++i) {
105108
++cnt[s[i]];
106-
while (cnt[s[i]] > 1 || i - j + 1 > k) {
107-
--cnt[s[j++]];
109+
if (--cnt[s[i - k]] == 0) {
110+
cnt.erase(s[i - k]);
108111
}
109-
ans += i - j + 1 == k;
112+
ans += cnt.size() == k;
110113
}
111114
return ans;
112115
}
@@ -115,17 +118,24 @@ public:
115118
116119
```go
117120
func numKLenSubstrNoRepeats(s string, k int) (ans int) {
118-
if k > len(s) || k > 26 {
119-
return 0
121+
n := len(s)
122+
if n < k {
123+
return
124+
}
125+
cnt := map[byte]int{}
126+
for i := 0; i < k; i++ {
127+
cnt[s[i]]++
128+
}
129+
if len(cnt) == k {
130+
ans++
120131
}
121-
cnt := [128]int{}
122-
for i, j := 0, 0; i < len(s); i++ {
132+
for i := k; i < n; i++ {
123133
cnt[s[i]]++
124-
for cnt[s[i]] > 1 || i-j+1 > k {
125-
cnt[s[j]]--
126-
j++
134+
cnt[s[i-k]]--
135+
if cnt[s[i-k]] == 0 {
136+
delete(cnt, s[i-k])
127137
}
128-
if i-j+1 == k {
138+
if len(cnt) == k {
129139
ans++
130140
}
131141
}
@@ -136,7 +146,7 @@ func numKLenSubstrNoRepeats(s string, k int) (ans int) {
136146
```ts
137147
function numKLenSubstrNoRepeats(s: string, k: number): number {
138148
const n = s.length;
139-
if (k > n) {
149+
if (n < k) {
140150
return 0;
141151
}
142152
const cnt: Map<string, number> = new Map();
@@ -164,120 +174,34 @@ class Solution {
164174
* @return Integer
165175
*/
166176
function numKLenSubstrNoRepeats($s, $k) {
167-
$sum = ($k * ($k + 1)) / 2 - $k;
168-
$cnt = $tmp = 0;
169-
for ($i = 0; $i < strlen($s) - $k + 1; $i++) {
170-
$str = substr($s, $i, $k);
171-
for ($j = 0; $j < $k; $j++) {
172-
$tmp += strpos($str, $str[$j]);
173-
}
174-
if ($tmp === $sum) {
175-
$cnt++;
176-
}
177-
$tmp = 0;
178-
}
179-
return $cnt;
180-
}
181-
}
182-
```
183-
184-
<!-- tabs:end -->
185-
186-
### 方法二
187-
188-
<!-- tabs:start -->
189-
190-
```python
191-
class Solution:
192-
def numKLenSubstrNoRepeats(self, s: str, k: int) -> int:
193-
n = len(s)
194-
if k > n:
195-
return 0
196-
cnt = Counter(s[:k])
197-
ans = int(len(cnt) == k)
198-
for i in range(k, n):
199-
cnt[s[i]] += 1
200-
cnt[s[i - k]] -= 1
201-
if cnt[s[i - k]] == 0:
202-
cnt.pop(s[i - k])
203-
ans += len(cnt) == k
204-
return ans
205-
```
206-
207-
```java
208-
class Solution {
209-
public int numKLenSubstrNoRepeats(String s, int k) {
210-
int n = s.length();
211-
if (k > n) {
177+
$n = strlen($s);
178+
if ($n < $k) {
212179
return 0;
213180
}
214-
Map<Character, Integer> cnt = new HashMap<>(k);
215-
for (int i = 0; i < k; ++i) {
216-
cnt.merge(s.charAt(i), 1, Integer::sum);
217-
}
218-
int ans = cnt.size() == k ? 1 : 0;
219-
for (int i = k; i < n; ++i) {
220-
cnt.merge(s.charAt(i), 1, Integer::sum);
221-
if (cnt.merge(s.charAt(i - k), -1, Integer::sum) == 0) {
222-
cnt.remove(s.charAt(i - k));
181+
$cnt = [];
182+
for ($i = 0; $i < $k; ++$i) {
183+
if (!isset($cnt[$s[$i]])) {
184+
$cnt[$s[$i]] = 1;
185+
} else {
186+
$cnt[$s[$i]]++;
223187
}
224-
ans += cnt.size() == k ? 1 : 0;
225-
}
226-
return ans;
227-
}
228-
}
229-
```
230-
231-
```cpp
232-
class Solution {
233-
public:
234-
int numKLenSubstrNoRepeats(string s, int k) {
235-
int n = s.size();
236-
if (k > n) {
237-
return 0;
238188
}
239-
unordered_map<char, int> cnt;
240-
for (int i = 0; i < k; ++i) {
241-
cnt[s[i]]++;
242-
}
243-
int ans = cnt.size() == k ? 1 : 0;
244-
for (int i = k; i < n; ++i) {
245-
cnt[s[i]]++;
246-
cnt[s[i - k]]--;
247-
if (cnt[s[i - k]] == 0) {
248-
cnt.erase(s[i - k]);
189+
$ans = count($cnt) == $k ? 1 : 0;
190+
for ($i = $k; $i < $n; ++$i) {
191+
if (!isset($cnt[$s[$i]])) {
192+
$cnt[$s[$i]] = 1;
193+
} else {
194+
$cnt[$s[$i]]++;
249195
}
250-
ans += cnt.size() == k ? 1 : 0;
196+
if ($cnt[$s[$i - $k]] - 1 == 0) {
197+
unset($cnt[$s[$i - $k]]);
198+
} else {
199+
$cnt[$s[$i - $k]]--;
200+
}
201+
$ans += count($cnt) == $k ? 1 : 0;
251202
}
252-
return ans;
203+
return $ans;
253204
}
254-
};
255-
```
256-
257-
```go
258-
func numKLenSubstrNoRepeats(s string, k int) (ans int) {
259-
n := len(s)
260-
if k > n {
261-
return 0
262-
}
263-
cnt := map[byte]int{}
264-
for i := 0; i < k; i++ {
265-
cnt[s[i]]++
266-
}
267-
if len(cnt) == k {
268-
ans++
269-
}
270-
for i := k; i < n; i++ {
271-
cnt[s[i]]++
272-
cnt[s[i-k]]--
273-
if cnt[s[i-k]] == 0 {
274-
delete(cnt, s[i-k])
275-
}
276-
if len(cnt) == k {
277-
ans++
278-
}
279-
}
280-
return
281205
}
282206
```
283207

0 commit comments

Comments
 (0)