@@ -77,15 +77,18 @@ tags:
7777
7878### 方法一:计数 + 双指针
7979
80- 我们用一个哈希表或数组 $need$ 统计字符串 $t$ 中每个字符出现的次数,用另一个哈希表或数组 $window$ 统计滑动窗口中每个字符出现的次数。另外,定义两个指针 $j $ 和 $i $ 分别指向窗口的左右边界,变量 $cnt$ 表示窗口中已经包含了 $t$ 中的多少个字符,变量 $k$ 和 $mi $ 分别表示最小覆盖子串的起始位置和长度。
80+ 我们用一个哈希表或数组 $\textit{ need} $ 统计字符串 $t$ 中每个字符出现的次数,用另一个哈希表或数组 $\textit{ window} $ 统计滑动窗口中每个字符出现的次数。另外,定义两个指针 $l $ 和 $r $ 分别指向窗口的左右边界,变量 $\textit{ cnt} $ 表示窗口中已经包含了 $t$ 中的多少个字符,变量 $k$ 和 $\textit{mi} $ 分别表示最小覆盖子串的起始位置和长度。
8181
82- 我们从左到右遍历字符串 $s$,对于当前遍历到的字符 $s[ i ] $:
82+ 我们从左到右遍历字符串 $s$,对于当前遍历到的字符 $s[ r ] $:
8383
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$ 右移一位,继续遍历即可。
8588
86- 遍历结束,如果没有找到最小覆盖子串,返回空字符串,否则返回 $s[ k: k +mi ] $ 即可。
89+ 遍历结束,如果没有找到最小覆盖子串,返回空字符串,否则返回 $s[ k: k +\textit{mi} ] $ 即可。
8790
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$。
8992
9093<!-- tabs:start -->
9194
@@ -96,20 +99,21 @@ class Solution:
9699 def minWindow (self , s : str , t : str ) -> str :
97100 need = Counter(t)
98101 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):
101105 window[c] += 1
102106 if need[c] >= window[c]:
103107 cnt += 1
104108 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 ]]:
109113 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]
113117```
114118
115119#### Java
@@ -119,25 +123,27 @@ class Solution {
119123 public String minWindow (String s , String t ) {
120124 int [] need = new int [128 ];
121125 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];
125128 }
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]) {
130134 ++ cnt;
131135 }
132136 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 ;
136140 }
137- if (need[s. charAt(j)] >= window[s. charAt(j)]) {
141+ c = s. charAt(l);
142+ if (window[c] <= need[c]) {
138143 -- cnt;
139144 }
140- -- window[s. charAt(j++ )];
145+ -- window[c];
146+ ++ l;
141147 }
142148 }
143149 return k < 0 ? " " : s. substring(k, k + mi);
@@ -151,29 +157,36 @@ class Solution {
151157class Solution {
152158public:
153159 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) {
158163 ++need[ c] ;
159164 }
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]) {
164172 ++cnt;
165173 }
174+
166175 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 ;
170179 }
171- if (need[ s[ j]] >= window[ s[ j]] ) {
180+
181+ c = s[l];
182+ if (window[c] <= need[c]) {
172183 --cnt;
173184 }
174- --window[ s[ j++]] ;
185+ --window[c];
186+ ++l;
175187 }
176188 }
189+
177190 return k < 0 ? "" : s.substr(k, mi);
178191 }
179192};
@@ -183,27 +196,32 @@ public:
183196
184197``` go
185198func 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] ]++
190203 }
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] {
195211 cnt++
196212 }
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
201217 }
202- if need[s[j]] >= window[s[j]] {
218+
219+ c = s[l]
220+ if window[c] <= need[c] {
203221 cnt--
204222 }
205- window[s[j] ]--
206- j ++
223+ window[c ]--
224+ l ++
207225 }
208226 }
209227 if k < 0 {
@@ -217,69 +235,80 @@ func minWindow(s string, t string) string {
217235
218236``` ts
219237function 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 )] ++ ;
224242 }
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 ++ ;
233249 }
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 ;
238254 }
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 -- ;
241259 }
242- -- window [s .charCodeAt (j ++ )];
260+ window [c ]-- ;
261+ l ++ ;
243262 }
244263 }
245- return k < 0 ? ' ' : s .slice (k , k + mi );
264+ return k < 0 ? ' ' : s .substring (k , k + mi );
246265}
247266```
248267
249268#### Rust
250269
251270``` rust
271+ use std :: collections :: HashMap ;
272+
252273impl Solution {
253274 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 ();
255277 for c in t . chars () {
256- need [ c as usize ] += 1 ;
278+ * need . entry ( c ) . or_insert ( 0 ) += 1 ;
257279 }
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 ) {
262292 cnt += 1 ;
263293 }
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 ;
269298 }
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 ) {
272302 cnt -= 1 ;
273303 }
274- window [ l ] -= 1 ;
275- j += 1 ;
304+ * window . entry ( c ) . or_insert ( 0 ) -= 1 ;
305+ l += 1 ;
276306 }
277307 }
278308 if k < 0 {
279- return "" . to_string ();
309+ return String :: new ();
280310 }
281- let k = k as usize ;
282- s [k .. k + mi ]. to_string ()
311+ s [k as usize .. (k as usize + mi )]. to_string ()
283312 }
284313}
285314```
@@ -291,26 +320,38 @@ public class Solution {
291320 public string MinWindow (string s , string t ) {
292321 int [] need = new int [128 ];
293322 int [] window = new int [128 ];
323+
294324 foreach (var c in t ) {
295- ++ need [c ];
325+ need [c ]++ ;
296326 }
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 ++ ;
302338 }
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 ;
307344 }
308- if (need [s [j ]] >= window [s [j ]]) {
309- -- cnt ;
345+
346+ c = s [l ];
347+ if (window [c ] <= need [c ]) {
348+ cnt -- ;
310349 }
311- -- window [s [j ++ ]];
350+ window [c ]-- ;
351+ l ++ ;
312352 }
313353 }
354+
314355 return k < 0 ? " " : s .Substring (k , mi );
315356 }
316357}
0 commit comments