原题链接在这里: 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).
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T, return the empty string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
题解:
把t的char和对应frequency放到map中. count最开始是t.length()
[walker, runner]窗口. s在runner的char若在map中,对应frequency--. count--
当count == 0时, 窗口罩住所有t的char.
移动walker, 直到下一个s在walker的char, 若在map中, 对应frequency++. count++.
Time Complexity: O(sLen). sLen = s.length().
Space: O(1). 256数组map.
AC Java:
1 public class Solution { 2 public String minWindow(String s, String t) { 3 if(s == null || t == null || s.length() < t.length()){ 4 return ""; 5 } 6 7 int [] map = new int[256]; 8 for(char c : t.toCharArray()){ 9 map[c]++; 10 } 11 12 int count = t.length(); 13 int minLen = Integer.MAX_VALUE; 14 int head = 0; 15 int walker = 0; 16 int runner = 0; 17 while(runner < s.length()){ 18 if(map[s.charAt(runner++)]-- > 0){ 19 count--; 20 } 21 while(count == 0){ //count == 0时就表示罩住所有t的char 22 if(runner - walker < minLen){ 23 minLen = runner - walker; 24 head = walker; 25 } 26 if(map[s.charAt(walker++)]++ == 0){ //让其罩不住所有t的char 27 count++; 28 } 29 } 30 } 31 return minLen == Integer.MAX_VALUE ? "" : s.substring(head, head+minLen); 32 } 33 }
类似Minimum Size Subarray Sum, Longest Substring Without Repeating Characters, Longest Substring with At Most Two Distinct Characters, Substring with Concatenation of All Words.
对于快慢指针找substring这类问题,通用这个方法.
1 int findSubstring(int s){ 2 int [] map = new int[256]; 3 int walker = 0; 4 int runner = 0; 5 int count; // check whether the substring is valid 6 int len; // length of substring 7 8 for(){ 9 /* 10 * initialize map. 11 */ 12 } 13 14 while(runner < s.length()){ 15 if(map[s.charAt(runner++)]-- ?){ 16 /* 17 * modify count. 18 */ 19 } 20 while(/*count condition*/){ 21 22 // update len here if finding minimum 23 24 if(map[s.charAt(walker++)]++ ?) { 25 //move walker to make it invalid/valid again 26 //modify count 27 } 28 } 29 30 //update len here if finding maximum 31 } 32 33 return len; 34 }
Note: 找maximum substring时,是在while loop 后面更新,因为需要while loop把substring 变valid.
找minimum substring时,是在while loop之中找, 因为while loop是要把substring 变invalid.
好比Longest Substring Without Repeating Characters.
1 public class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 int res = 0; 4 int [] map = new int[256]; 5 int count = 0; 6 int walker = 0; 7 int runner = 0; 8 9 while(runner < s.length()){ 10 if(map[s.charAt(runner++)]++ > 0){ 11 count++; 12 } 13 while(count > 0){ 14 if(map[s.charAt(walker++)]-- > 1){ 15 count--; 16 } 17 } 18 res = Math.max(res, runner-walker); 19 } 20 return res; 21 } 22 }
和Longest Substring with At Most Two Distinct Characters
1 public class Solution { 2 public int lengthOfLongestSubstringTwoDistinct(String s) { 3 int res = 0; 4 int [] map = new int[256]; 5 int walker = 0; 6 int runner = 0; 7 int count = 0; 8 while(runner < s.length()){ 9 if(map[s.charAt(runner++)]++ == 0){ 10 count++; 11 } 12 while(count > 2){ 13 if(map[s.charAt(walker++)]-- == 1){ 14 count--; 15 } 16 } 17 res = Math.max(res, runner - walker); 18 } 19 return res; 20 } 21 }
都是在while loop后面找maximum的substring. 以为while loop 使 substring valid.