76. Minimum Window Substring [LeetCode]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jacky_chenjp/article/details/75155436

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.

题目描述:给定两个字符串S和T,求出S中的最短子串,满足条件:该子串中的部分或全部字符可以重新排列组合形成字符串T。

题目要求:算法的时间复杂度为O(n)。

思路分析:该问题可以直接brute force求解,但暴力解法的时间复杂度显然无法达到题目要求。这里采用了在字符串处理中较为常用的方法:先建立一个字典,然后维护一个窗口,在原字符串上滑动求解。

具体的做法是:

首先。遍历字符串T,建立以字符--出现次数为键值对的HashMap,时间复杂度为O(m);

然后,遍历字符串S,维护这个HashMap:(这里的时间复杂度为O(n))

1. 如果字符不在字典中,就直接跳过不处理;

2. 否则,遇到字典中字符就将对应字符的数量减一,如果当前字符是以窗口left--right中组成字符串T仍然需要的,就将count++,表示目前已经取到了count个组成字符串T所必需的字符了;

3. 接着,如果count与T的长度相等,就判断此时的窗口长度是否比之前记录的最小长度小,如果是,就将最小长度值更新,最小长度对应的起点标记为start;

4. 为了继续向后遍历,需要将left不断向右推,判断当前left是否为组成T的必需字符,如果是,将count--,使count不再等于T的长度,迫使对S的遍历继续进行,否则,只要将left向右推即可;

综上所述,空间复杂度也就是T字符串的长度O(m)。注:在分析中默认满足n>=m,否则就属于corner case,可以直接返回空串。

代码如下:

public class Solution {
    public String minWindow(String s, String t) {
        // corner case
        int sLen = s.length();
        int tLen = t.length();
        if (sLen < tLen || sLen==0 || tLen==0) {
            return "";
        }
        
        // initialize the hashmap for each character in target string
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i=0; i<tLen; i++) {
            if (map.containsKey(t.charAt(i))) {
                map.put(t.charAt(i), map.get(t.charAt(i))+1);
            } else {
                map.put(t.charAt(i), 1);
            }
        }
        
        int minLen = Integer.MAX_VALUE;
        int left = 0;
        int start = 0;
        int count = 0;
        
        // the time complexity is O(n)
        for (int right=0; right<sLen; right++) {
            if (map.containsKey(s.charAt(right))) {
                // change the value in hashmap
                map.put(s.charAt(right), map.get(s.charAt(right))-1);
                if (map.get(s.charAt(right))>=0) {
                    // the character is valid
                    count++;
                }
                while (count==tLen) {
                    // the target string 
                    if (right-left+1<minLen) {
                        minLen = right-left+1;
                        start = left;
                    }
                    if (map.containsKey(s.charAt(left))) {
                        map.put(s.charAt(left), map.get(s.charAt(left))+1);
                        if (map.get(s.charAt(left))>0) {
                            // the left character is used in target string
                            count--;
                        }
                    }
                    left++;
                }
            }
        }
        
        if (minLen==Integer.MAX_VALUE) {
            return "";
        }
        return s.substring(start, start+minLen);
    }
}



猜你喜欢

转载自blog.csdn.net/Jacky_chenjp/article/details/75155436