友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

支付宝

微信

有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

wx jikerizhi

公众号的微信号是: jikerizhi因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。

76. Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

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

Note:

  • If there is no such window in S that covers all characters in T, return the empty string "".

  • If there is such window, you are guaranteed that there will always be only one unique minimum window in S.

思路分析

滑动窗口

0076 01
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
 * Runtime: 489 ms, faster than 5.03% of Java online submissions for Minimum Window Substring.
 * Memory Usage: 322.8 MB, less than 5.32% of Java online submissions for Minimum Window Substring.
 *
 * ↓ 优化:在最后输出时,才截取字符串。
 *
 * Runtime: 33 ms, faster than 16.02% of Java online submissions for Minimum Window Substring.
 * Memory Usage: 44.4 MB, less than 5.32% of Java online submissions for Minimum Window Substring.
 */
public String minWindow(String s, String t) {
    if (Objects.isNull(s) || s.length() == 0
            || Objects.isNull(t) || t.length() == 0
            || s.length() < t.length()) {
        return "";
    }
    Map<Character, Integer> needs = new HashMap<>(t.length());
    for (char c : t.toCharArray()) {
        needs.put(c, needs.getOrDefault(c, 0) + 1);
    }
    int left = 0, right = 0;
    int minLength = Integer.MAX_VALUE;
    int start = 0;
    int match = 0;
    Map<Character, Integer> windows = new HashMap<>(t.length());
    while (right < s.length()) {
        char rChar = s.charAt(right);
        if (needs.containsKey(rChar)) {
            int rCount = windows.getOrDefault(rChar, 0) + 1;
            windows.put(rChar, rCount);
            if (rCount == needs.get(rChar)) {
                match++;
            }
        }
        right++;

        while (match == needs.size()) {
            if (right - left < minLength) {
                minLength = right - left;
                start = left;
            }
            char lChar = s.charAt(left);
            if (needs.containsKey(lChar)) {
                int lCount = windows.get(lChar) - 1;
                windows.put(lChar, lCount);
                if (lCount < needs.get(lChar)) {
                    match--;
                }
            }
            left++;
        }

    }
    return minLength == Integer.MAX_VALUE ? "" : s.substring(start, start + minLength);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
 * 自己实现失败后,参考社区答案修改的
 */
public String minWindow(String s, String t) {
  if (s == null || s.isEmpty() || t == null || t.isEmpty() || s.length() < t.length()) {
    return "";
  }

  // 初始化 need,记录 t 中每个字符的出现次数
  char[] chars = s.toCharArray();
  Map<Character, Integer> need = new HashMap<>();
  for (char c : t.toCharArray()) {
    need.put(c, need.getOrDefault(c, 0) + 1);
  }

  Map<Character, Integer> window = new HashMap<>();

  int left = 0, right = 0; // 窗口的左右边界
  int valid = 0; // 已经匹配上的字符数量
  int start = 0, minLen = Integer.MAX_VALUE; // 最小窗口的起始位置和长度

  while (right < s.length()) {
    // 扩大窗口
    char rc = chars[right];
    right++;

    // 更新窗口内字符的计数
    if (need.containsKey(rc)) {
      window.put(rc, window.getOrDefault(rc, 0) + 1);
      if (window.get(rc).equals(need.get(rc))) {
        valid++;
      }
    }

    // 收缩窗口
    while (need.size() == valid) {
      // 更新最小窗口的起始位置和长度
      if (right - left < minLen) {
        start = left;
        minLen = right - left;
      }

      char lc = chars[left];
      // 缩小窗口,移动左边界
      if (need.containsKey(lc)) {
        window.put(lc, window.get(lc) - 1);
        if (window.get(lc) < need.get(lc)) {
          valid--;
        }
      }
      left++;
    }
  }
  return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
}