Leetcode 76. Minimum Window Substring(Hard)

来源:互联网 发布:jmeter调用java代码 编辑:程序博客网 时间:2024/06/11 02:08

Problem :

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:

S = “ADOBECODEBANC”
T = “ABC”
Minimum window is “BANC”

Algorithm:

本题意为在S中寻找T的一个最小覆盖串。其中,最小覆盖串是这样一 个串,它包含T的所有字符且串长度最小。本题O(n2)的做法是从S第一个字符开始逐个枚举最小覆盖串。即以第一个字符为覆盖串左端点,向右寻找右端点,再以第二个字符为左端点,以此类推,直到遍历完整个S串。第二种做法也称为取尺法,具体做法为:设最小覆盖串的左右端点分别为i和j。令i、j初始值为0,即S串最左端,j向右移动,直到满足条件(即包含T所有字符)停止,接着,i开始向右移动,直到不再满足条件或i>j为止。重复上述过程,直到j到达S最右端。其中,判断满足条件的方法为:我们先记录T串每个字符的数量,然后用left表示当前覆盖串左端点,right表示右端点,sat表示是否满足条件,min_len记录最短串长。在遍历S串过程中,若当前字符没有达到满足条件的数量,则令sat++。当sat==t的长度时,满足条件,开始对i右移,即上面所描述的过程。当某次i右移后,当前字符没有达到满足条件的数量时,sat--,串再次不满足条件。因为i和j均是一直向右移动,中间不存在回退的情况,因此只会遍历一次S串,所以算法时间复杂度为O(n)。

Code:

const int INF = 1 << 29;int ruler[256];int check[256];class Solution {public:    string minWindow(string s, string t) {        memset(ruler, 0, sizeof(ruler));        memset(check, 0, sizeof(check));        for(int i = 0; i < t.size(); ++i) {            ruler[t[i]]++;        }        int sat = 0;        int left = 0, right = 0, min_len = INF;        for(int i = 0, j = 0; j < s.size(); ++j) {            if(sat < t.size()) {                if(check[s[j]] < ruler[s[j]]) sat++;                check[s[j]]++;            }            if(sat == t.size()) {                while(check[s[i]] > ruler[s[i]] && i <= j) {                    check[s[i]]--;                    i++;                }                if(min_len > j - i + 1){                    left = i;                    right = j;                    min_len = j - i + 1;                }                while(sat == t.size() && i <= j) {                    check[s[i]]--;                    if(check[s[i]] < ruler[s[i]]) sat--;                    i++;                }            }        }        string ans;        if(min_len < INF) return ans.assign(s, left, right - left + 1);        else return "";    }};
0 0