68
68
69
69
### 方法一:哈希表
70
70
71
- 遍历字符串 $ s$,用一个哈希表存储所有长度为 $k$ 的不同子串。只需要判断子串数能否达到 $ 2^k$ 即可 。
71
+ 首先,对于一个长度为 $n$ 的字符串 $ s$,长度为 $k$ 的子串的个数为 $n - k + 1$,如果 $n - k + 1 < 2^k$,则一定存在长度为 $k$ 的二进制串不是 $s$ 的子串,返回 ` false ` 。
72
72
73
- 时间复杂度 $O(n \times k)$,其中 $n$ 是字符串 $s$ 的长度,$k$ 是子串长度。
73
+ 接下来,我们遍历字符串 $s$,将所有长度为 $k$ 的子串存入集合 $ss$,最后判断集合 $ss$ 的大小是否等于 $2^k$。
74
+
75
+ 时间复杂度 $O(n \times k)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。
74
76
75
77
<!-- tabs:start -->
76
78
@@ -79,20 +81,29 @@ tags:
79
81
``` python
80
82
class Solution :
81
83
def hasAllCodes (self , s : str , k : int ) -> bool :
82
- ss = {s[i : i + k] for i in range (len (s) - k + 1 )}
83
- return len (ss) == 1 << k
84
+ n = len (s)
85
+ m = 1 << k
86
+ if n - k + 1 < m:
87
+ return False
88
+ ss = {s[i : i + k] for i in range (n - k + 1 )}
89
+ return len (ss) == m
84
90
```
85
91
86
92
#### Java
87
93
88
94
``` java
89
95
class Solution {
90
96
public boolean hasAllCodes (String s , int k ) {
97
+ int n = s. length();
98
+ int m = 1 << k;
99
+ if (n - k + 1 < m) {
100
+ return false ;
101
+ }
91
102
Set<String > ss = new HashSet<> ();
92
- for (int i = 0 ; i < s . length() - k + 1 ; ++ i) {
103
+ for (int i = 0 ; i < n - k + 1 ; ++ i) {
93
104
ss. add(s. substring(i, i + k));
94
105
}
95
- return ss. size() == 1 << k ;
106
+ return ss. size() == m ;
96
107
}
97
108
}
98
109
```
@@ -103,11 +114,16 @@ class Solution {
103
114
class Solution {
104
115
public:
105
116
bool hasAllCodes(string s, int k) {
117
+ int n = s.size();
118
+ int m = 1 << k;
119
+ if (n - k + 1 < m) {
120
+ return false;
121
+ }
106
122
unordered_set<string > ss;
107
- for (int i = 0; i + k <= s.size() ; ++i) {
123
+ for (int i = 0; i + k <= n ; ++i) {
108
124
ss.insert(move(s.substr(i, k)));
109
125
}
110
- return ss.size() == 1 << k ;
126
+ return ss.size() == m ;
111
127
}
112
128
};
113
129
```
@@ -116,11 +132,32 @@ public:
116
132
117
133
```go
118
134
func hasAllCodes(s string, k int) bool {
135
+ n, m := len(s), 1<<k
136
+ if n-k+1 < m {
137
+ return false
138
+ }
119
139
ss := map[string]bool{}
120
- for i := 0; i+k <= len(s) ; i++ {
140
+ for i := 0; i+k <= n ; i++ {
121
141
ss[s[i:i+k]] = true
122
142
}
123
- return len(ss) == 1<<k
143
+ return len(ss) == m
144
+ }
145
+ ```
146
+
147
+ #### TypeScript
148
+
149
+ ``` ts
150
+ function hasAllCodes(s : string , k : number ): boolean {
151
+ const n = s .length ;
152
+ const m = 1 << k ;
153
+ if (n - k + 1 < m ) {
154
+ return false ;
155
+ }
156
+ const ss = new Set <string >();
157
+ for (let i = 0 ; i + k <= n ; ++ i ) {
158
+ ss .add (s .slice (i , i + k ));
159
+ }
160
+ return ss .size === m ;
124
161
}
125
162
```
126
163
@@ -132,9 +169,9 @@ func hasAllCodes(s string, k int) bool {
132
169
133
170
### 方法二:滑动窗口
134
171
135
- 方法一中,我们存储了所有长度为 $k$ 的不同子串,子串的处理需要 $O(k)$ 的时间,我们可以改用滑动窗口,每次添加最新字符时,删除窗口最左边的字符。此过程中用一个整型数字 $num $ 来存放子串。
172
+ 方法一中,我们存储了所有长度为 $k$ 的不同子串,子串的处理需要 $O(k)$ 的时间,我们可以改用滑动窗口,每次添加最新字符时,删除窗口最左边的字符。此过程中用一个整型数字 $x $ 来存放子串。
136
173
137
- 时间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。
174
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。 其中 $n$ 是字符串 $s$ 的长度。
138
175
139
176
<!-- tabs: start -->
140
177
@@ -143,17 +180,19 @@ func hasAllCodes(s string, k int) bool {
143
180
``` python
144
181
class Solution :
145
182
def hasAllCodes (self , s : str , k : int ) -> bool :
146
- if len (s) - k + 1 < (1 << k):
183
+ n = len (s)
184
+ m = 1 << k
185
+ if n - k + 1 < m:
147
186
return False
148
- vis = [ False ] * ( 1 << k )
149
- num = int (s[:k], 2 )
150
- vis[num] = True
151
- for i in range (k, len (s) ):
152
- a = ( ord ( s[i - k]) - ord ( ' 0 ' ) ) << (k - 1 )
153
- b = ord (s[i]) - ord ( ' 0 ' )
154
- num = ((num - a) << 1 ) + b
155
- vis[num] = True
156
- return all (v for v in vis)
187
+ ss = set ( )
188
+ x = int (s[:k], 2 )
189
+ ss.add(x)
190
+ for i in range (k, n ):
191
+ a = int ( s[i - k]) << (k - 1 )
192
+ b = int (s[i])
193
+ x = (x - a) << 1 | b
194
+ ss.add(x)
195
+ return len (ss) == m
157
196
```
158
197
159
198
#### Java
@@ -162,19 +201,20 @@ class Solution:
162
201
class Solution {
163
202
public boolean hasAllCodes (String s , int k ) {
164
203
int n = s. length();
165
- if (n - k + 1 < (1 << k)) {
204
+ int m = 1 << k;
205
+ if (n - k + 1 < m) {
166
206
return false ;
167
207
}
168
- boolean [] vis = new boolean [1 << k ];
169
- int num = Integer . parseInt(s. substring(0 , k), 2 );
170
- vis[num ] = true ;
208
+ boolean [] ss = new boolean [m ];
209
+ int x = Integer . parseInt(s. substring(0 , k), 2 );
210
+ ss[x ] = true ;
171
211
for (int i = k; i < n; ++ i) {
172
212
int a = (s. charAt(i - k) - ' 0' ) << (k - 1 );
173
213
int b = s. charAt(i) - ' 0' ;
174
- num = (num - a) << 1 | b;
175
- vis[num ] = true ;
214
+ x = (x - a) << 1 | b;
215
+ ss[x ] = true ;
176
216
}
177
- for (boolean v : vis ) {
217
+ for (boolean v : ss ) {
178
218
if (! v) {
179
219
return false ;
180
220
}
@@ -191,19 +231,21 @@ class Solution {
191
231
public:
192
232
bool hasAllCodes(string s, int k) {
193
233
int n = s.size();
194
- if (n - k + 1 < (1 << k)) return false;
195
- vector<bool > vis(1 << k);
196
- int num = stoi(s.substr(0, k), nullptr, 2);
197
- vis[ num] = true;
234
+ int m = 1 << k;
235
+ if (n - k + 1 < m) {
236
+ return false;
237
+ }
238
+ bool ss[ m] ;
239
+ memset(ss, false, sizeof(ss));
240
+ int x = stoi(s.substr(0, k), nullptr, 2);
241
+ ss[ x] = true;
198
242
for (int i = k; i < n; ++i) {
199
243
int a = (s[ i - k] - '0') << (k - 1);
200
244
int b = s[ i] - '0';
201
- num = (num - a) << 1 | b;
202
- vis [ num ] = true;
245
+ x = (x - a) << 1 | b;
246
+ ss [ x ] = true;
203
247
}
204
- for (bool v : vis)
205
- if (!v) return false;
206
- return true;
248
+ return all_of(ss, ss + m, [ ] (bool v) { return v; });
207
249
}
208
250
};
209
251
```
@@ -212,22 +254,20 @@ public:
212
254
213
255
```go
214
256
func hasAllCodes(s string, k int) bool {
215
- n := len(s)
216
- if n-k+1 < (1 << k) {
257
+ n, m := len(s), 1<<k
258
+ if n-k+1 < m {
217
259
return false
218
260
}
219
- vis := make([]bool, 1<<k)
220
- num := 0
221
- for i := 0; i < k; i++ {
222
- num = num<<1 | int(s[i]-'0')
223
- }
224
- vis[num] = true
261
+ ss := make([]bool, m)
262
+ x, _ := strconv.ParseInt(s[:k], 2, 64)
263
+ ss[x] = true
225
264
for i := k; i < n; i++ {
226
- a := int(s[i-k]-'0') << (k - 1)
227
- num = (num-a)<<1 | int(s[i]-'0')
228
- vis[num] = true
265
+ a := int64(s[i-k]-'0') << (k - 1)
266
+ b := int64(s[i] - '0')
267
+ x = (x-a)<<1 | b
268
+ ss[x] = true
229
269
}
230
- for _, v := range vis {
270
+ for _, v := range ss {
231
271
if !v {
232
272
return false
233
273
}
@@ -236,6 +276,28 @@ func hasAllCodes(s string, k int) bool {
236
276
}
237
277
```
238
278
279
+ #### TypeScript
280
+
281
+ ``` ts
282
+ function hasAllCodes(s : string , k : number ): boolean {
283
+ const n = s .length ;
284
+ const m = 1 << k ;
285
+ if (n - k + 1 < m ) {
286
+ return false ;
287
+ }
288
+ let x = + ` 0b${s .slice (0 , k )} ` ;
289
+ const ss = new Set <number >();
290
+ ss .add (x );
291
+ for (let i = k ; i < n ; ++ i ) {
292
+ const a = + s [i - k ] << (k - 1 );
293
+ const b = + s [i ];
294
+ x = ((x - a ) << 1 ) | b ;
295
+ ss .add (x );
296
+ }
297
+ return ss .size === m ;
298
+ }
299
+ ```
300
+
239
301
<!-- tabs: end -->
240
302
241
303
<!-- solution: end -->
0 commit comments