[LeetCode] 76. Minimum Window Substring

最小覆盖子串。题意是给两个字符串S和T,S较长,请找出S中最短的包含T中所有字母的子串。例子,

Example:

Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"

思路依然是滑动窗口(sliding window),但是这个版本的题解是具有普适性的,可以套用到多个LC的题目中。如下是几个细节,

  • 创建一个hashmap,记录T中出现的字母及其次数
  • 创建一个变量count去记录T的长度
  • 创建两个指针left和right,一前一后扫描S,right在前,left在后,去卡S里面的子串,看这个子串里面是否包含T中所有的字符
  • 最后跳出循环的条件是right已经扫描完整个S的长度

扫描的一开始,是end往前走,每遇到一个字符,无论他在不在T中,就都去map中--这个字符;如果这个字符在T中也有,同时也要去count--。当count == 0的时候,证明此时的子串已经包含了T中所有的字母了,可以考虑缩减start和end之间的距离了。缩减的条件是while (count == 0),去看end - start是否能缩短那个最小长度minLen,同时开始挪动start指针;若能缩短,也要记录一个变量minStart,这样就能记住最短的子串到底从什么位置开始的。挪动的时候也要去map中++当前遍历到的字符。如果当前字符在map中的value大于0了,count也需要++,因为这说明有一个字符已经不在子串中了,此时会跳出while循环。最后最短子串是s.substring(minStart, minStart + minLen)。

时间O(n)

空间O(1)

Java实现

 1 class Solution {
 2     public String minWindow(String s, String t) {
 3         int[] map = new int[128];
 4         for (char c : t.toCharArray()) {
 5             map[c]++;
 6         }
 7         int start = 0;
 8         int end = 0;
 9         int minStart = 0;
10         int minLen = Integer.MAX_VALUE;
11         int counter = t.length();
12         while (end < s.length()) {
13             char c1 = s.charAt(end);
14             if (map[c1] > 0) {
15                 counter--;
16             }
17             map[c1]--;
18             end++;
19             while (counter == 0) {
20                 if (minLen > end - start) {
21                     minLen = end - start;
22                     minStart = start;
23                 }
24                 char c2 = s.charAt(start);
25                 map[c2]++;
26                 if (map[c2] > 0) {
27                     counter++;
28                 }
29                 start++;
30             }
31         }
32         return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
33     }
34 }

 

JavaScript实现

 1 /**
 2  * @param {string} s
 3  * @param {string} t
 4  * @return {string}
 5  */
 6 var minWindow = function (s, t) {
 7     let ans = '';
 8     // save all the letters in t to a hashmap
 9     let map = {};
10     t.split('').forEach(ch => map[ch] = (map[ch] || 0) + 1);
11     let count = Object.keys(map).length;
12 
13     // traverse s
14     let l = 0;
15     let r = -1;
16     while (r < s.length) {
17         if (count === 0) {
18             // l~r contains t
19             if (!ans || r - l + 1 < ans.length) {
20                 ans = s.slice(l, r + 1);
21             }
22             // get rid of curr ch and then move l
23             if (map[s[l]] !== undefined) {
24                 map[s[l]]++;
25             }
26             if (map[s[l]] > 0) {
27                 count++;
28             }
29             l++;
30         } else {
31             // l~r doesn't contain t
32             // move r and add new ch
33             r++;
34             if (map[s[r]] !== undefined) {
35                 map[s[r]]--;
36             }
37             if (map[s[r]] === 0) {
38                 count--;
39             }
40         }
41     }
42     return ans;
43 };

 

你可能感兴趣的:([LeetCode] 76. Minimum Window Substring)