76.Minimum-Window-Substring

76. Minimum Window Substring

้ข˜็›ฎๅœฐๅ€

https://leetcode.com/problems/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.

ไปฃ็ 

Approach #1 Sliding Window

ๅŒๆŒ‡้’ˆ + ๅŒๅญ—ๅ…ธ (้œ€่ฆๅŒน้…็š„ๅญ—ๅ…ธ๏ผŒ็ช—ๅฃๅ†…็š„ๅญ—ๅ…ธ)

  1. ๅ›บๅฎšๅทฆ่พนl, r++ๅพ€ๅณๆž„ๅปบๆปก่ถณๆกไปถ็š„map

  2. ๅฝ“ๆปก่ถณๆกไปถ๏ผŒๅ›บๅฎšๅณ่พนr๏ผŒl++็ผฉๅฐๅณ็ซฏๆฃ€ๆŸฅๆ˜ฏๅฆๆปก่ถณmap

Time Complexity && Space Complexity: O(|S| + |T|)

class Solution {
  public String minWindow(String s, String t) {
      if (s.length() == 0 || t.length() == 0) return "";

      // Dictionary which keeps a count of all the unique characters in t.
      Map<Character, Integer> dictT = new HashMap<Character, Integer>();
      for (int i = 0; i < t.length(); i++) {
          int count = dictT.getOrDefault(t.charAt(i), 0);
          dictT.put(t.charAt(i), count + 1);
      }
      // ans list of the form (window length, left, right)
      int[] ans = {-1, 0, 0};

      Map<Character, Integer> windowCounts = new HashMap<Character, Integer>();
      int required = dictT.size();
      int formed = 0;

      // Left and Right pointer
      int l = 0, r = 0;
      while (r < s.length()) {
          char c = s.charAt(r);
          int count = windowCounts.getOrDefault(c, 0);
          windowCounts.put(c, count + 1);

          if (dictT.containsKey(c) 
              && windowCounts.get(c).intValue() == dictT.get(c).intValue()) {
              formed++;
          }

          // Try and contract the window till the point where it ceases to be 'desirable'.
          while (l <= r && formed == required) {
              c = s.charAt(l);
              // Save the smallest window until now.
              if (ans[0] == -1 || r - l + 1 < ans[0]) {
                  ans[0] = r - l + 1;
                  ans[1] = l;
                  ans[2] = r;
              }
              // The character at the position pointed by the
              // `Left` pointer is no longer a part of the window.
              windowCounts.put(c, windowCounts.get(c) - 1);
              if (dictT.containsKey(c) && windowCounts.get(c).intValue() < dictT.get(c).intValue()) {
                  formed--;
              }
              // Move the left pointer ahead, this would help to look for a new window.
              l++;
          }

          // Keep expanding the window once we are done contracting.
          r++;   
      }

      return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1);
  }
}

Approach #2 Optimized Sliding Window

class Solution {
  public String minWindow(String s, String t) {
    if (s.length() == 0 || t.length() == 0) return "";

    Map<Character, Integer> dictT = new HashMap<Character, Integer>();
    for (int i = 0; i < t.length(); i++) {
      int count = dictT.getOrDefault(t.charAt(i), 0);
      dictT.put(t.charAt(i), count + 1);
    }
    int required = dictT.size();

    List<Pair<Integer, Character>> filteredS = new ArrayList<Pair<Integer, Character>>();
    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);
      if (dictT.containsKey(c)) {
        filteredS.add(new Pair<Integer, Character>(i, c));
      }
    }

    int l = 0, r = 0, formed = 0;
    Map<Character, Integer> windowCounts = new HashMap<Character, Integer>();
    int[] ans = {-1, 0, 0};

    while (r < filteredS.size()) {
      char c = filteredS.get(r).getValue();
      int count = windowCounts.getOrDefault(c, 0);
      windowCounts.put(c, count + 1);

      if (dictT.containsKey(c) &&
         windowCounts.get(c).intValue() == dictT.get(c).intValue()) {
        formed++;
      }

      while (l <= r && formed == required) {
        c = filteredS.get(l).getValue();
        int end = filteredS.get(r).getKey();
        int start = filteredS.get(l).getKey();
        if (ans[0] == -1 || end - start + 1 < ans[0]) {
          ans[0] = end - start + 1;
          ans[1] = start;
          ans[2] = end;
        }

        windowCounts.put(c, windowCounts.get(c) - 1);
        if (dictT.containsKey(c) 
            && windowCounts.get(c).intValue() < dictT.gt(c).intValue()) {
          formed--;
        }
        i++;
      }
      r++;
    }

    return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1);
  }
}

Last updated