Minimum Window Substring (Unsolved)

given two strings, say it’s S and T.
we need to find the minimum windows in S that contains every chars in T, and we don’t need them to be in the exactly same order.
please do this in a time complexity of O(N)

other things needs to keep in mind:
if there is no such window in S, then return “”
we are guaranteed that there only exist one windows that meet our requirement.

idea:
order is not matter.

question: if T is “AABC”, does that mean the minimum window have to contains at least two As? or one A is enough?

let’s assume we need one A/to contains everything .
then we will mark every chars in S who showed in T, and we need to find the shortest substring that contains every char in T.
of course we can using sliding window to solve problems like this.

we need to initialize a sliding window, and all the two pointers will be placed in index of 0. besides, two variables will be maintained in order to find the shortest length and its corresponding substring.
and the next problem is: how can I check if current window contains all chars required?
we can use the brute force way to check it: if every char in T can find a char in this substring of S. then that means current substring is a potential result.
and then we need to move sliding window to find another potential results.but how? are we moving left pointer by one, and check again? if it is still a potential result then we keeps moving left pointer until it is not. then we fixed this pointer, and move the right pointer to find next potential position.
the brute force way can check it, but not efficiently especially when we move only one step at a time. so a number/variable need to be maintained, which mean, if this number drops to 0, then that means a new potential result is found.

BUT, how to check that? how to check them?
I used two hashmap arrays. one used to count, one used to check. and I use a variable ‘remain’ to maintain how many char should we add it order to include all chars in T.

class Solution {
    public String minWindow(String s, String t) {
        if (s == null || s.length() == 0) return null;
        if (t == null || t.length() == 0) return "";
        
        int i = 0;
        int j = 0;
        int minLength = Integer.MAX_VALUE;
        int[] map = new int[128];
        int[] mapCopy = new int[128];
        
        for (char c: t.toCharArray()) {
            map[c]++;
            mapCopy[c]++;
            
        }
        
        
        int remain = t.length();
        String res = "";
        
        while (i <= s.length() - t.length()) {
            System.out.println(i);
            
            while (j < s.length() && remain > 0) { //moving j only, in the whole process, the length keeps increasing
                j++;
                if (map[s.charAt(j)] > 0) {
                    map[s.charAt(j)]--;
                    remain--;
                }
                
            }
            if (j == s.length() - 1) {
                if (remain == 0) {
                    if (minLength > j - i + 1) {
                        return s.substring(i, j + 1);
                    } else {
                        return res;
                    }
                } else {
                    break;
                }
                
            } 
            System.out.println(j);
            if (minLength > j - i + 1) {
                minLength = Math.min(minLength, j - i + 1);
                res = s.substring(i, j + 1);
            }
            
            //now we need to move i for a shorter answer
            while (remain == 0) { //this while will relocate i to the next position, and it's guaranteed that i will move at least one step
                i++;
                if (mapCopy[s.charAt(i-1)] > 0) { //if this char is contained in t
                    map[s.charAt(i-1)]++;
                    remain++;
                }
            }
            
        }
        return res;
            
        
    }
   
}

and the following is the accepted code I wrote few months ago,

class Solution {
    public String minWindow(String s, String t) {
        if (s == null || t == null || s.length() == 0 || t.length() == 0) {
            return null;
        }
        int m = s.length();
        int n = t.length();
        HashMap<Character, Integer> map = new HashMap<>();
        for (char c: t.toCharArray()) {
            map.put(c, map.getOrDefault(c, 0) + 1);
        } 
        //keep in mind that as long as the substring in s contains all the characters(even the number has to be the same) in t is valid
        int required = map.size();
        int l = 0; //left pointer
        int r = 0;
        
        int formed = 0;//it seems this var is the number of unique chars in t. only when formed == required, at that time, right pointer expanding stops
        
        //this hashmap keeps track of all the characters in substring
        HashMap<Character, Integer> windowCounts = new HashMap<Character, Integer>();
        
        int[] ans = {-1, 0, 0}; //{windowslength, left, right}, both are tight bound
        
        while (r < m) {
            char c = s.charAt(r);
            windowCounts.put(c, windowCounts.getOrDefault(c, 0) + 1);
            
            if (map.containsKey(c) && windowCounts.get(c).equals(map.get(c))) {
                formed++; //the means we have one char satisfied
            }
            
            //shrink phrase
            while (l <= r && formed == required) { //because we need to find the shortest, so we keeps moving
                c = s.charAt(l);
                if (ans[0] == -1 || r - l + 1 < ans[0]) { //if ans[0] havn't initialized or we have shorter solution
                    //update the info in ans
                    ans[0] = r - l + 1;
                    ans[1] = l;
                    ans[2] = r;
                }
                //and we also needs to update windowCounts
                windowCounts.put(c, windowCounts.get(c) - 1);
                //and update formed
                if (map.containsKey(c) && windowCounts.get(c).compareTo(map.get(c)) < 0) {
                    formed--;
                }
                //left pointer moves forward
                l++;
            }
            //update right pointer
            r++;
        }
        
        return ans[0] == -1? "": s.substring(ans[1], ans[2] + 1);
        
    }
}

the general idea is pretty much the same, not quite sure why my code is not working.

posted @ 2020-09-12 11:27  EvanMeetTheWorld  阅读(21)  评论(0)    收藏  举报