传送门:https://leetcode-cn.com/probl...
困难题,手动狗头
动态规划想了想感觉无法作为子问题求解,卒。
联想到滑动窗口,似乎是个可以解决的方法。
看到用例

S = "ADOBECODEBANC", T = "ABC"

1. 为T的每一个字符分配一个哈希表,记录其位于滑窗中的出现位置,滑窗中还没有该字符则赋值为0.考虑到0的问题,将赋值统一+1
2. 从S的首字符开始遍历,遍历过程中将遇到以下几种情况:

  • S[i]∉T。即该字符不包含在T内,直接跳过
  • S[i]∈T,map[s[i]]=0。即该字符包含在T内,且该数从前未出现过。则map[s[i]] = i
  • S[i]∈T,map[s[i]]!=0。即该字符包含在T内,但该数已经出现。这里就比较复杂,简单来说分为如下几步:
    1.更新map : map[s[i]] = i。
    2.若该字符是该滑窗的首字符,则更新滑窗范围,这里就需要查询map中value最小的key。由于需要查找的是value,查询耗时O(n)

3. 遍历过程中,引入计数器count,若count = len(T),则每发生一次滑窗变动都要比较这个滑窗与当前最小滑窗的大小。
4. 遍历完成,返回最小滑窗。
image.png
出人意料,查看一下用例。原来T字符串是可以重复的。那你倒是早说啊┗|`O′|┛
重新审视一下代码过程:
思考过程不多说了,还是走了一点弯路。
再引入一个countMap记录每个字符的出现次数,遍历的三种情况做如下变换:

  • S[i]∉T。即该字符不包含在T内,直接跳过
  • S[i]∈T,map[s[i]]=0。即该字符包含在T内,且该数从前未出现过。则map[s[i]] = i
  • S[i]∈T,map[s[i]]!=0,countMap[s[i]]>0。即该字符包含在T内,该字符出现过,但还没有出现完整。countMap[s[i]]--
  • S[i]∈T,map[s[i]]!=0,countMap[s[i]]>0。即该字符包含在T内,该字符出现过,且出现完整。这里就比较复杂,简单来说分为如下几步:
    1.更新map : map[s[i]] = 滑窗内第二次出现si。由于map只记录了第一次,这里需要遍历滑窗,查询耗时O(n)
    2.若该字符是该滑窗的首字符,则更新滑窗范围,这里就需要查询map中value最小的key。由于需要查找的是value,查询耗时O(n)
class Solution {
public:
    string minWindow(string s, string t) {
        int lenofS = s.length();
        int lenofT = t.length();
        map<char,int> visitMap;
        map<char,int> countMap;
        char first = 0;
        int begin=0,end=0;
        int count = 0;
        int min = 0;
        int start=0,finish=0;
        for(int i=0;i<lenofT;++i){
            countMap[t[i]]++;
            visitMap[t[i]] = 0;
        } 
        while(end<lenofS){
            //是目标数
            if(visitMap.find(s[end])!=visitMap.end()){
                if(!first){ first = s[end];begin=end;}
                //窗口没有这个数
                if(visitMap[s[end]] == 0){
                    visitMap[s[end]] = end+1;count++;
                    countMap[s[end]]--;
                    if(count==lenofT){
                        min = end-begin+1;start=begin;finish=end;
                    }
                }
                else if(countMap[s[end]]>0){
                    count++;
                    countMap[s[end]]--;
                    if(count==lenofT){
                        min = end-begin+1;start=begin;finish=end;
                    }
                }
                //有这个数,更新其地址
                else if(visitMap[s[end]] != 0){
                    for(int i=visitMap[s[end]];i<=end;++i){
                        if(s[i]==s[end]){
                            visitMap[s[end]] = i+1;
                            break;
                        }
                    }
                    if(first==s[end]){
                        first = findSecond(visitMap);
                        begin = visitMap[first] - 1;
                    }
                }
                if(count == lenofT && min>end-begin+1) {
                    min = end - begin + 1;
                    start=begin;finish=end;
                }
                end++;
            }
            else{
                if(!first) begin++;
                end++;
                cout<<"no"<<endl;
            }
        }
        if(count!=lenofT) return "";
        if(finish==0) s.substr(0,1);
        return s.substr(start,finish-start+1);
    }
    char findSecond(map<char,int> &visitMap){
        map<char,int>::iterator it;
        it=visitMap.begin();
        int min = it->second;char index = it->first;
        for(;it!=visitMap.end();++it){
            if(min ==0 || (it->second != 0 && it->second < min )){
                min = it->second;index = it->first;
            }
        }
        return index;
    }
};

image.png
再看看有没有更好的方法。


HHXXHGGZ
0 声望0 粉丝

下一篇 »
Leetcode 449