Skip to content

Commit f87a7aa

Browse files
committed
feat: add solutions to lc problem: No.1100
No.1100.Find K-Length Substrings With No Repeated Characters
1 parent e34ee97 commit f87a7aa

File tree

6 files changed

+137
-112
lines changed

6 files changed

+137
-112
lines changed

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

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@
3939

4040
<!-- 这里可写通用的实现逻辑 -->
4141

42-
固定大小的滑动窗口。
42+
**方法一:双指针 + 计数器**
43+
44+
我们观察发现,字符均为小写字母,也即最多有 $26$ 种不同的字符。因此,如果 $k \gt 26$ 或者 $k \gt n$,则无法找到任何长度为 $k$ 且不含重复字符的子串,直接返回 $0$ 即可。
45+
46+
接下来,我们用双指针 $j$ 和 $i$ 维护一个滑动窗口,其中 $j$ 是滑动窗口的左端点,$i$ 是滑动窗口的右端点,用一个计数器 $cnt$ 统计滑动窗口中每个字符出现的次数。
47+
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$,则说明滑动窗口中的字符串是一个符合题意的子串,将结果加一。
49+
50+
遍历结束后,即可得到所有符合题意的子串的个数。
51+
52+
时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度;而 $C$ 为字符集的大小,本题中 $C = 26$。
4353

4454
<!-- tabs:start -->
4555

@@ -50,14 +60,17 @@
5060
```python
5161
class Solution:
5262
def numKLenSubstrNoRepeats(self, s: str, k: int) -> int:
63+
n = len(s)
64+
if k > n or k > 26:
65+
return 0
5366
ans = j = 0
54-
mp = {}
67+
cnt = Counter()
5568
for i, c in enumerate(s):
56-
if c in mp:
57-
j = max(j, mp[c] + 1)
58-
mp[c] = i
59-
if i - j + 1 >= k:
60-
ans += 1
69+
cnt[c] += 1
70+
while cnt[c] > 1 or i - j + 1 > k:
71+
cnt[s[j]] -= 1
72+
j += 1
73+
ans += i - j + 1 == k
6174
return ans
6275
```
6376

@@ -68,17 +81,18 @@ class Solution:
6881
```java
6982
class Solution {
7083
public int numKLenSubstrNoRepeats(String s, int k) {
84+
int n = s.length();
85+
if (k > n || k > 26) {
86+
return 0;
87+
}
88+
int[] cnt = new int[128];
7189
int ans = 0;
72-
Map<Character, Integer> mp = new HashMap<>();
73-
for (int i = 0, j = 0; i < s.length(); ++i) {
74-
char c = s.charAt(i);
75-
if (mp.containsKey(c)) {
76-
j = Math.max(j, mp.get(c) + 1);
77-
}
78-
mp.put(c, i);
79-
if (i - j + 1 >= k) {
80-
++ans;
90+
for (int i = 0, j = 0; i < n; ++i) {
91+
++cnt[s.charAt(i)];
92+
while (cnt[s.charAt(i)] > 1 || i - j + 1 > k) {
93+
cnt[s.charAt(j++)]--;
8194
}
95+
ans += i - j + 1 == k ? 1 : 0;
8296
}
8397
return ans;
8498
}
@@ -91,13 +105,18 @@ class Solution {
91105
class Solution {
92106
public:
93107
int numKLenSubstrNoRepeats(string s, int k) {
108+
int n = s.size();
109+
if (k > n || k > 26) {
110+
return 0;
111+
}
112+
int cnt[128]{};
94113
int ans = 0;
95-
unordered_map<int, int> mp;
96-
for (int i = 0, j = 0; i < s.size(); ++i) {
97-
char c = s[i];
98-
if (mp.count(c)) j = max(j, mp[c] + 1);
99-
mp[c] = i;
100-
if (i - j + 1 >= k) ++ans;
114+
for (int i = 0, j = 0; i < n; ++i) {
115+
++cnt[s[i]];
116+
while (cnt[s[i]] > 1 || i - j + 1 > k) {
117+
--cnt[s[j++]];
118+
}
119+
ans += i - j + 1 == k;
101120
}
102121
return ans;
103122
}
@@ -107,26 +126,22 @@ public:
107126
### **Go**
108127
109128
```go
110-
func numKLenSubstrNoRepeats(s string, k int) int {
111-
mp := make(map[rune]int)
112-
ans, j := 0, 0
113-
for i, c := range s {
114-
if v, ok := mp[c]; ok {
115-
j = max(j, v+1)
129+
func numKLenSubstrNoRepeats(s string, k int) (ans int) {
130+
if k > len(s) || k > 26 {
131+
return 0
132+
}
133+
cnt := [128]int{}
134+
for i, j := 0, 0; i < len(s); i++ {
135+
cnt[s[i]]++
136+
for cnt[s[i]] > 1 || i-j+1 > k {
137+
cnt[s[j]]--
138+
j++
116139
}
117-
mp[c] = i
118-
if i-j+1 >= k {
140+
if i-j+1 == k {
119141
ans++
120142
}
121143
}
122-
return ans
123-
}
124-
125-
func max(a, b int) int {
126-
if a > b {
127-
return a
128-
}
129-
return b
144+
return
130145
}
131146
```
132147

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

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,17 @@
4141
```python
4242
class Solution:
4343
def numKLenSubstrNoRepeats(self, s: str, k: int) -> int:
44+
n = len(s)
45+
if k > n or k > 26:
46+
return 0
4447
ans = j = 0
45-
mp = {}
48+
cnt = Counter()
4649
for i, c in enumerate(s):
47-
if c in mp:
48-
j = max(j, mp[c] + 1)
49-
mp[c] = i
50-
if i - j + 1 >= k:
51-
ans += 1
50+
cnt[c] += 1
51+
while cnt[c] > 1 or i - j + 1 > k:
52+
cnt[s[j]] -= 1
53+
j += 1
54+
ans += i - j + 1 == k
5255
return ans
5356
```
5457

@@ -57,17 +60,18 @@ class Solution:
5760
```java
5861
class Solution {
5962
public int numKLenSubstrNoRepeats(String s, int k) {
63+
int n = s.length();
64+
if (k > n || k > 26) {
65+
return 0;
66+
}
67+
int[] cnt = new int[128];
6068
int ans = 0;
61-
Map<Character, Integer> mp = new HashMap<>();
62-
for (int i = 0, j = 0; i < s.length(); ++i) {
63-
char c = s.charAt(i);
64-
if (mp.containsKey(c)) {
65-
j = Math.max(j, mp.get(c) + 1);
66-
}
67-
mp.put(c, i);
68-
if (i - j + 1 >= k) {
69-
++ans;
69+
for (int i = 0, j = 0; i < n; ++i) {
70+
++cnt[s.charAt(i)];
71+
while (cnt[s.charAt(i)] > 1 || i - j + 1 > k) {
72+
cnt[s.charAt(j++)]--;
7073
}
74+
ans += i - j + 1 == k ? 1 : 0;
7175
}
7276
return ans;
7377
}
@@ -80,13 +84,18 @@ class Solution {
8084
class Solution {
8185
public:
8286
int numKLenSubstrNoRepeats(string s, int k) {
87+
int n = s.size();
88+
if (k > n || k > 26) {
89+
return 0;
90+
}
91+
int cnt[128]{};
8392
int ans = 0;
84-
unordered_map<int, int> mp;
85-
for (int i = 0, j = 0; i < s.size(); ++i) {
86-
char c = s[i];
87-
if (mp.count(c)) j = max(j, mp[c] + 1);
88-
mp[c] = i;
89-
if (i - j + 1 >= k) ++ans;
93+
for (int i = 0, j = 0; i < n; ++i) {
94+
++cnt[s[i]];
95+
while (cnt[s[i]] > 1 || i - j + 1 > k) {
96+
--cnt[s[j++]];
97+
}
98+
ans += i - j + 1 == k;
9099
}
91100
return ans;
92101
}
@@ -96,26 +105,22 @@ public:
96105
### **Go**
97106
98107
```go
99-
func numKLenSubstrNoRepeats(s string, k int) int {
100-
mp := make(map[rune]int)
101-
ans, j := 0, 0
102-
for i, c := range s {
103-
if v, ok := mp[c]; ok {
104-
j = max(j, v+1)
108+
func numKLenSubstrNoRepeats(s string, k int) (ans int) {
109+
if k > len(s) || k > 26 {
110+
return 0
111+
}
112+
cnt := [128]int{}
113+
for i, j := 0, 0; i < len(s); i++ {
114+
cnt[s[i]]++
115+
for cnt[s[i]] > 1 || i-j+1 > k {
116+
cnt[s[j]]--
117+
j++
105118
}
106-
mp[c] = i
107-
if i-j+1 >= k {
119+
if i-j+1 == k {
108120
ans++
109121
}
110122
}
111-
return ans
112-
}
113-
114-
func max(a, b int) int {
115-
if a > b {
116-
return a
117-
}
118-
return b
123+
return
119124
}
120125
```
121126

solution/1100-1199/1100.Find K-Length Substrings With No Repeated Characters/Solution.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
class Solution {
22
public:
33
int numKLenSubstrNoRepeats(string s, int k) {
4+
int n = s.size();
5+
if (k > n || k > 26) {
6+
return 0;
7+
}
8+
int cnt[128]{};
49
int ans = 0;
5-
unordered_map<int, int> mp;
6-
for (int i = 0, j = 0; i < s.size(); ++i) {
7-
char c = s[i];
8-
if (mp.count(c)) j = max(j, mp[c] + 1);
9-
mp[c] = i;
10-
if (i - j + 1 >= k) ++ans;
10+
for (int i = 0, j = 0; i < n; ++i) {
11+
++cnt[s[i]];
12+
while (cnt[s[i]] > 1 || i - j + 1 > k) {
13+
--cnt[s[j++]];
14+
}
15+
ans += i - j + 1 == k;
1116
}
1217
return ans;
1318
}
Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
func numKLenSubstrNoRepeats(s string, k int) int {
2-
mp := make(map[rune]int)
3-
ans, j := 0, 0
4-
for i, c := range s {
5-
if v, ok := mp[c]; ok {
6-
j = max(j, v+1)
1+
func numKLenSubstrNoRepeats(s string, k int) (ans int) {
2+
if k > len(s) || k > 26 {
3+
return 0
4+
}
5+
cnt := [128]int{}
6+
for i, j := 0, 0; i < len(s); i++ {
7+
cnt[s[i]]++
8+
for cnt[s[i]] > 1 || i-j+1 > k {
9+
cnt[s[j]]--
10+
j++
711
}
8-
mp[c] = i
9-
if i-j+1 >= k {
12+
if i-j+1 == k {
1013
ans++
1114
}
1215
}
13-
return ans
14-
}
15-
16-
func max(a, b int) int {
17-
if a > b {
18-
return a
19-
}
20-
return b
16+
return
2117
}

solution/1100-1199/1100.Find K-Length Substrings With No Repeated Characters/Solution.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
class Solution {
22
public int numKLenSubstrNoRepeats(String s, int k) {
3+
int n = s.length();
4+
if (k > n || k > 26) {
5+
return 0;
6+
}
7+
int[] cnt = new int[128];
38
int ans = 0;
4-
Map<Character, Integer> mp = new HashMap<>();
5-
for (int i = 0, j = 0; i < s.length(); ++i) {
6-
char c = s.charAt(i);
7-
if (mp.containsKey(c)) {
8-
j = Math.max(j, mp.get(c) + 1);
9-
}
10-
mp.put(c, i);
11-
if (i - j + 1 >= k) {
12-
++ans;
9+
for (int i = 0, j = 0; i < n; ++i) {
10+
++cnt[s.charAt(i)];
11+
while (cnt[s.charAt(i)] > 1 || i - j + 1 > k) {
12+
cnt[s.charAt(j++)]--;
1313
}
14+
ans += i - j + 1 == k ? 1 : 0;
1415
}
1516
return ans;
1617
}
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
class Solution:
22
def numKLenSubstrNoRepeats(self, s: str, k: int) -> int:
3+
n = len(s)
4+
if k > n or k > 26:
5+
return 0
36
ans = j = 0
4-
mp = {}
7+
cnt = Counter()
58
for i, c in enumerate(s):
6-
if c in mp:
7-
j = max(j, mp[c] + 1)
8-
mp[c] = i
9-
if i - j + 1 >= k:
10-
ans += 1
9+
cnt[c] += 1
10+
while cnt[c] > 1 or i - j + 1 > k:
11+
cnt[s[j]] -= 1
12+
j += 1
13+
ans += i - j + 1 == k
1114
return ans

0 commit comments

Comments
 (0)