@@ -77,15 +77,18 @@ tags:
77
77
78
78
### 方法一:计数 + 双指针
79
79
80
- 我们用一个哈希表或数组 $need$ 统计字符串 $t$ 中每个字符出现的次数,用另一个哈希表或数组 $window$ 统计滑动窗口中每个字符出现的次数。另外,定义两个指针 $j $ 和 $i $ 分别指向窗口的左右边界,变量 $cnt$ 表示窗口中已经包含了 $t$ 中的多少个字符,变量 $k$ 和 $mi $ 分别表示最小覆盖子串的起始位置和长度。
80
+ 我们用一个哈希表或数组 $\textit{ need} $ 统计字符串 $t$ 中每个字符出现的次数,用另一个哈希表或数组 $\textit{ window} $ 统计滑动窗口中每个字符出现的次数。另外,定义两个指针 $l $ 和 $r $ 分别指向窗口的左右边界,变量 $\textit{ cnt} $ 表示窗口中已经包含了 $t$ 中的多少个字符,变量 $k$ 和 $\textit{mi} $ 分别表示最小覆盖子串的起始位置和长度。
81
81
82
- 我们从左到右遍历字符串 $s$,对于当前遍历到的字符 $s[ i ] $:
82
+ 我们从左到右遍历字符串 $s$,对于当前遍历到的字符 $s[ r ] $:
83
83
84
- 我们将其加入窗口中,即 $window[ s[ i]] = window[ s[ i]] + 1$,如果此时 $need[ s[ i]] \geq window[ s[ i]] $,则说明 $s[ i] $ 是一个「必要的字符」,我们将 $cnt$ 加一。如果 $cnt$ 等于 $t$ 的长度,说明此时窗口中已经包含了 $t$ 中的所有字符,我们就可以尝试更新最小覆盖子串的起始位置和长度了。如果 $i - j + 1 \lt mi$,说明当前窗口表示的子串更短,我们就更新 $mi = i - j + 1$ 和 $k = j$。然后,我们尝试移动左边界 $j$,如果此时 $need[ s[ j]] \geq window[ s[ j]] $,则说明 $s[ j] $ 是一个「必要的字符」,移动左边界时会把 $s[ j] $ 这个字符从窗口中移除,因此我们需要将 $cnt$ 减一,然后更新 $window[ s[ j]] = window[ s[ j]] - 1$,并将 $j$ 右移一位。如果 $cnt$ 与 $t$ 的长度不相等,说明此时窗口中还没有包含 $t$ 中的所有字符,我们就不需要移动左边界了,直接将 $i$ 右移一位,继续遍历即可。
84
+ - 我们将其加入窗口中,即 $\textit{window}[ s[ r]] = \textit{window}[ s[ r]] + 1$,如果此时 $\textit{need}[ s[ r]] \geq \textit{window}[ s[ r]] $,则说明 $s[ r] $ 是一个「必要的字符」,我们将 $\textit{cnt}$ 加一。
85
+ - 如果 $\textit{cnt}$ 等于 $t$ 的长度,说明此时窗口中已经包含了 $t$ 中的所有字符,我们就可以尝试更新最小覆盖子串的起始位置和长度了。如果 $r - l + 1 < \textit{mi}$,说明当前窗口表示的子串更短,我们就更新 $\textit{mi} = r - l + 1$ 和 $k = l$。
86
+ - 然后,我们尝试移动左边界 $l$,如果此时 $\textit{need}[ s[ l]] \geq \textit{window}[ s[ l]] $,则说明 $s[ l] $ 是一个「必要的字符」,移动左边界时会把 $s[ l] $ 这个字符从窗口中移除,因此我们需要将 $\textit{cnt}$ 减一,然后更新 $\textit{window}[ s[ l]] = \textit{window}[ s[ l]] - 1$,并将 $l$ 右移一位。
87
+ - 如果 $\textit{cnt}$ 与 $t$ 的长度不相等,说明此时窗口中还没有包含 $t$ 中的所有字符,我们就不需要移动左边界了,直接将 $r$ 右移一位,继续遍历即可。
85
88
86
- 遍历结束,如果没有找到最小覆盖子串,返回空字符串,否则返回 $s[ k: k +mi ] $ 即可。
89
+ 遍历结束,如果没有找到最小覆盖子串,返回空字符串,否则返回 $s[ k: k +\textit{mi} ] $ 即可。
87
90
88
- 时间复杂度 $O(m + n)$,空间复杂度 $O(C )$。其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度;而 $C $ 是字符集的大小,本题中 $C = 128$。
91
+ 时间复杂度 $O(m + n)$,空间复杂度 $O(|\Sigma| )$。其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度;而 $|\Sigma| $ 是字符集的大小,本题中 $|\Sigma| = 128$。
89
92
90
93
<!-- tabs:start -->
91
94
@@ -96,20 +99,21 @@ class Solution:
96
99
def minWindow (self , s : str , t : str ) -> str :
97
100
need = Counter(t)
98
101
window = Counter()
99
- cnt, j, k, mi = 0 , 0 , - 1 , inf
100
- for i, c in enumerate (s):
102
+ cnt = l = 0
103
+ k, mi = - 1 , inf
104
+ for r, c in enumerate (s):
101
105
window[c] += 1
102
106
if need[c] >= window[c]:
103
107
cnt += 1
104
108
while cnt == len (t):
105
- if i - j + 1 < mi:
106
- mi = i - j + 1
107
- k = j
108
- if need[s[j ]] >= window[s[j ]]:
109
+ if r - l + 1 < mi:
110
+ mi = r - l + 1
111
+ k = l
112
+ if need[s[l ]] >= window[s[l ]]:
109
113
cnt -= 1
110
- window[s[j ]] -= 1
111
- j += 1
112
- return ' ' if k < 0 else s[k : k + mi]
114
+ window[s[l ]] -= 1
115
+ l += 1
116
+ return " " if k < 0 else s[k : k + mi]
113
117
```
114
118
115
119
#### Java
@@ -119,25 +123,27 @@ class Solution {
119
123
public String minWindow (String s , String t ) {
120
124
int [] need = new int [128 ];
121
125
int [] window = new int [128 ];
122
- int m = s. length(), n = t. length();
123
- for (int i = 0 ; i < n; ++ i) {
124
- ++ need[t. charAt(i)];
126
+ for (char c : t. toCharArray()) {
127
+ ++ need[c];
125
128
}
126
- int cnt = 0 , j = 0 , k = - 1 , mi = 1 << 30 ;
127
- for (int i = 0 ; i < m; ++ i) {
128
- ++ window[s. charAt(i)];
129
- if (need[s. charAt(i)] >= window[s. charAt(i)]) {
129
+ int m = s. length(), n = t. length();
130
+ int k = - 1 , mi = m + 1 , cnt = 0 ;
131
+ for (int l = 0 , r = 0 ; r < m; ++ r) {
132
+ char c = s. charAt(r);
133
+ if (++ window[c] <= need[c]) {
130
134
++ cnt;
131
135
}
132
136
while (cnt == n) {
133
- if (i - j + 1 < mi) {
134
- mi = i - j + 1 ;
135
- k = j ;
137
+ if (r - l + 1 < mi) {
138
+ mi = r - l + 1 ;
139
+ k = l ;
136
140
}
137
- if (need[s. charAt(j)] >= window[s. charAt(j)]) {
141
+ c = s. charAt(l);
142
+ if (window[c] <= need[c]) {
138
143
-- cnt;
139
144
}
140
- -- window[s. charAt(j++ )];
145
+ -- window[c];
146
+ ++ l;
141
147
}
142
148
}
143
149
return k < 0 ? " " : s. substring(k, k + mi);
@@ -151,29 +157,36 @@ class Solution {
151
157
class Solution {
152
158
public:
153
159
string minWindow(string s, string t) {
154
- int need[ 128] {};
155
- int window[ 128] {};
156
- int m = s.size(), n = t.size();
157
- for (char& c : t) {
160
+ vector<int > need(128, 0);
161
+ vector<int > window(128, 0);
162
+ for (char c : t) {
158
163
++need[ c] ;
159
164
}
160
- int cnt = 0, j = 0, k = -1, mi = 1 << 30;
161
- for (int i = 0; i < m; ++i) {
162
- ++window[ s[ i]] ;
163
- if (need[ s[ i]] >= window[ s[ i]] ) {
165
+
166
+ int m = s.length(), n = t.length();
167
+ int k = -1, mi = m + 1, cnt = 0;
168
+
169
+ for (int l = 0, r = 0; r < m; ++r) {
170
+ char c = s[r];
171
+ if (++window[c] <= need[c]) {
164
172
++cnt;
165
173
}
174
+
166
175
while (cnt == n) {
167
- if (i - j + 1 < mi) {
168
- mi = i - j + 1;
169
- k = j ;
176
+ if (r - l + 1 < mi) {
177
+ mi = r - l + 1;
178
+ k = l ;
170
179
}
171
- if (need[ s[ j]] >= window[ s[ j]] ) {
180
+
181
+ c = s[l];
182
+ if (window[c] <= need[c]) {
172
183
--cnt;
173
184
}
174
- --window[ s[ j++]] ;
185
+ --window[c];
186
+ ++l;
175
187
}
176
188
}
189
+
177
190
return k < 0 ? "" : s.substr(k, mi);
178
191
}
179
192
};
@@ -183,27 +196,32 @@ public:
183
196
184
197
``` go
185
198
func minWindow (s string , t string ) string {
186
- need := [128 ]int{}
187
- window := [128 ]int{}
188
- for _, c := range t {
189
- need[c ]++
199
+ need := make ([ ]int , 128 )
200
+ window := make ([ ]int , 128 )
201
+ for i := 0 ; i < len (t); i++ {
202
+ need[t[i] ]++
190
203
}
191
- cnt, j, k, mi := 0, 0, -1, 1<<30
192
- for i, c := range s {
193
- window[c]++
194
- if need[c] >= window[c] {
204
+
205
+ m , n := len (s), len (t)
206
+ k , mi , cnt := -1 , m+1 , 0
207
+
208
+ for l , r := 0 , 0 ; r < m; r++ {
209
+ c := s[r]
210
+ if window[c]++; window[c] <= need[c] {
195
211
cnt++
196
212
}
197
- for cnt == len(t) {
198
- if i-j +1 < mi {
199
- mi = i - j + 1
200
- k = j
213
+ for cnt == n {
214
+ if r-l +1 < mi {
215
+ mi = r - l + 1
216
+ k = l
201
217
}
202
- if need[s[j]] >= window[s[j]] {
218
+
219
+ c = s[l]
220
+ if window[c] <= need[c] {
203
221
cnt--
204
222
}
205
- window[s[j] ]--
206
- j ++
223
+ window[c ]--
224
+ l ++
207
225
}
208
226
}
209
227
if k < 0 {
@@ -217,69 +235,80 @@ func minWindow(s string, t string) string {
217
235
218
236
``` ts
219
237
function minWindow(s : string , t : string ): string {
220
- const need: number [] = new Array (128 ).fill (0 );
221
- const window: number [] = new Array (128 ).fill (0 );
222
- for (const c of t ) {
223
- ++ need [c .charCodeAt (0 )] ;
238
+ const need: number [] = Array (128 ).fill (0 );
239
+ const window: number [] = Array (128 ).fill (0 );
240
+ for (let i = 0 ; i < t . length ; i ++ ) {
241
+ need [t .charCodeAt (i )] ++ ;
224
242
}
225
- let cnt = 0 ;
226
- let j = 0 ;
227
- let k = - 1 ;
228
- let mi = 1 << 30 ;
229
- for (let i = 0 ; i < s .length ; ++ i ) {
230
- ++ window [s .charCodeAt (i )];
231
- if (need [s .charCodeAt (i )] >= window [s .charCodeAt (i )]) {
232
- ++ cnt ;
243
+ const [m, n] = [s .length , t .length ];
244
+ let [k, mi, cnt] = [- 1 , m + 1 , 0 ];
245
+ for (let l = 0 , r = 0 ; r < m ; r ++ ) {
246
+ let c = s .charCodeAt (r );
247
+ if (++ window [c ] <= need [c ]) {
248
+ cnt ++ ;
233
249
}
234
- while (cnt === t . length ) {
235
- if (i - j + 1 < mi ) {
236
- mi = i - j + 1 ;
237
- k = j ;
250
+ while (cnt === n ) {
251
+ if (r - l + 1 < mi ) {
252
+ mi = r - l + 1 ;
253
+ k = l ;
238
254
}
239
- if (need [s .charCodeAt (j )] >= window [s .charCodeAt (j )]) {
240
- -- cnt ;
255
+
256
+ c = s .charCodeAt (l );
257
+ if (window [c ] <= need [c ]) {
258
+ cnt -- ;
241
259
}
242
- -- window [s .charCodeAt (j ++ )];
260
+ window [c ]-- ;
261
+ l ++ ;
243
262
}
244
263
}
245
- return k < 0 ? ' ' : s .slice (k , k + mi );
264
+ return k < 0 ? ' ' : s .substring (k , k + mi );
246
265
}
247
266
```
248
267
249
268
#### Rust
250
269
251
270
``` rust
271
+ use std :: collections :: HashMap ;
272
+
252
273
impl Solution {
253
274
pub fn min_window (s : String , t : String ) -> String {
254
- let (mut need , mut window , mut cnt ) = ([0 ; 256 ], [0 ; 256 ], 0 );
275
+ let mut need : HashMap <char , usize > = HashMap :: new ();
276
+ let mut window : HashMap <char , usize > = HashMap :: new ();
255
277
for c in t . chars () {
256
- need [ c as usize ] += 1 ;
278
+ * need . entry ( c ) . or_insert ( 0 ) += 1 ;
257
279
}
258
- let (mut j , mut k , mut mi ) = (0 , - 1 , 1 << 31 );
259
- for (i , c ) in s . chars (). enumerate () {
260
- window [c as usize ] += 1 ;
261
- if need [c as usize ] >= window [c as usize ] {
280
+ let m = s . len ();
281
+ let n = t . len ();
282
+ let mut k = - 1 ;
283
+ let mut mi = m + 1 ;
284
+ let mut cnt = 0 ;
285
+
286
+ let s_bytes = s . as_bytes ();
287
+ let mut l = 0 ;
288
+ for r in 0 .. m {
289
+ let c = s_bytes [r ] as char ;
290
+ * window . entry (c ). or_insert (0 ) += 1 ;
291
+ if window [& c ] <= * need . get (& c ). unwrap_or (& 0 ) {
262
292
cnt += 1 ;
263
293
}
264
-
265
- while cnt == t . len () {
266
- if i - j + 1 < mi {
267
- k = j as i32 ;
268
- mi = i - j + 1 ;
294
+ while cnt == n {
295
+ if r - l + 1 < mi {
296
+ mi = r - l + 1 ;
297
+ k = l as i32 ;
269
298
}
270
- let l = s . chars (). nth (j ). unwrap () as usize ;
271
- if need [l ] >= window [l ] {
299
+
300
+ let c = s_bytes [l ] as char ;
301
+ if window [& c ] <= * need . get (& c ). unwrap_or (& 0 ) {
272
302
cnt -= 1 ;
273
303
}
274
- window [ l ] -= 1 ;
275
- j += 1 ;
304
+ * window . entry ( c ) . or_insert ( 0 ) -= 1 ;
305
+ l += 1 ;
276
306
}
277
307
}
278
308
if k < 0 {
279
- return "" . to_string ();
309
+ return String :: new ();
280
310
}
281
- let k = k as usize ;
282
- s [k .. k + mi ]. to_string ()
311
+ s [k as usize .. (k as usize + mi )]. to_string ()
283
312
}
284
313
}
285
314
```
@@ -291,26 +320,38 @@ public class Solution {
291
320
public string MinWindow (string s , string t ) {
292
321
int [] need = new int [128 ];
293
322
int [] window = new int [128 ];
323
+
294
324
foreach (var c in t ) {
295
- ++ need [c ];
325
+ need [c ]++ ;
296
326
}
297
- int cnt = 0 , j = 0 , k = - 1 , mi = 1 << 30 ;
298
- for (int i = 0 ; i < s .Length ; ++ i ) {
299
- ++ window [s [i ]];
300
- if (need [s [i ]] >= window [s [i ]]) {
301
- ++ cnt ;
327
+
328
+ int m = s .Length , n = t .Length ;
329
+ int k = - 1 , mi = m + 1 , cnt = 0 ;
330
+
331
+ int l = 0 ;
332
+ for (int r = 0 ; r < m ; r ++ ) {
333
+ char c = s [r ];
334
+ window [c ]++ ;
335
+
336
+ if (window [c ] <= need [c ]) {
337
+ cnt ++ ;
302
338
}
303
- while (cnt == t .Length ) {
304
- if (i - j + 1 < mi ) {
305
- mi = i - j + 1 ;
306
- k = j ;
339
+
340
+ while (cnt == n ) {
341
+ if (r - l + 1 < mi ) {
342
+ mi = r - l + 1 ;
343
+ k = l ;
307
344
}
308
- if (need [s [j ]] >= window [s [j ]]) {
309
- -- cnt ;
345
+
346
+ c = s [l ];
347
+ if (window [c ] <= need [c ]) {
348
+ cnt -- ;
310
349
}
311
- -- window [s [j ++ ]];
350
+ window [c ]-- ;
351
+ l ++ ;
312
352
}
313
353
}
354
+
314
355
return k < 0 ? " " : s .Substring (k , mi );
315
356
}
316
357
}
0 commit comments