ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

leetcode76.最小覆盖子串(困难)

2021-10-19 11:03:05  阅读:140  来源: 互联网

标签:子串 right hash minlen ++ 最小 enough leetcode76 left


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
双指针经典题目,可以看一下leetcode.209

自己的思路:
记录出s中每个字符后面该字符的位置,当left指针移动之后,导致窗口内少了一个字符,right直接移动到left之前指向的那个字符。
自己的思路存在的问题: 注意题目中t的字符是可重复的,如果不重复的话才可以这样做!
官方思路:
双指针。
难点:
1:如何判断right移动后的的窗口是否包含了t中所有的字符?
可以设置两个hash表(窗口内t中的字符搞一个, t搞一个),对这两个hash表逐个比较,如果存在一个字符,s_hash(该字符)<
t_hash(该字符) 则不满足
2:left right两个指针如何让移动?
right移动一直移动直到移动到可以满足的位置(窗口内元素个数>=t中的元素个数)之后。然后left一个一个进行移动,移动一次判断一次,并对ans更新。

class Solution {
public:
    unordered_map<char, int> s_hash, t_hash;
    bool enough();
    string minWindow(string s, string t) {
        //滑动窗口经典题目.
        //s_hash记录t中出现的字符的个数,t_hash记录t中字符的个数
        int n = s.size(), m = t.size();
        for (int i = 0; i < m; ++i) {
            t_hash[t[i]]++;
        }
        int left = 0, right = -1, ans_left, minlen = INT_MAX;
        while (right < n - 1) {
            right++;
            if (t_hash.find(s[right]) != t_hash.end()) {
                s_hash[s[right]]++;
            }
            if (enough()) {
                while (left < right && enough()) {
                    if (right - left + 1 < minlen) {
                        minlen = right - left + 1;
                        ans_left = left;
                    }
                    if (t_hash.find(s[left]) != t_hash.end()) {
                        s_hash[s[left]]--;
                    }
                    left++;
                }
                if (left == right && enough()) {
                    minlen = right - left + 1;
                    ans_left = left;
                }
            }
            
        }
        return minlen == INT_MAX ? "" : s.substr(ans_left, minlen);
    }
};
bool Solution::enough() {
    for (auto &m: t_hash) {
        if (s_hash[m.first] < m.second) return false;
    }
    return true;
}

改进:
上面的代码中,right移动的位置是0-n-1,可以缩小范围,把下标缩减([index1, index2],index1和index2指向的元素都是t中出现的元素)。

//改进如下:
class Solution {
public:
    unordered_map<char, int> s_hash, t_hash;
    bool enough();
    string minWindow(string s, string t) {

        int n = s.size(), m = t.size();
        int index1 = 0, index2 = n - 1; //下标范围
        for (int i = 0; i < m; ++i) {
            t_hash[t[i]]++;
        }
        while (index1 < n && t_hash.find(s[index1]) == t_hash.end()) index1++;  //index1移动
        while (index2 >= 0 && t_hash.find(s[index2]) == t_hash.end()) index2--; //index2移动
        int left = index1, right = index1 - 1, ans_left, minlen = INT_MAX;
        while (right < index2) { //right最多移动到index2的位置
            right++; 
            if (t_hash.find(s[right]) != t_hash.end()) {
                s_hash[s[right]]++;
            }
            if (enough()) {
                while (left < right && enough()) {
                    if (right - left + 1 < minlen) {
                        minlen = right - left + 1;
                        ans_left = left;
                    }
                    if (t_hash.find(s[left]) != t_hash.end()) {
                        s_hash[s[left]]--;
                    }
                    left++;
                }
                if (left == right && enough()) {
                    minlen = right - left + 1;
                    ans_left = left;
                }
            }
            
        }
        return minlen == INT_MAX ? "" : s.substr(ans_left, minlen);
    }
};
bool Solution::enough() {
    for (auto &m: t_hash) {
        if (s_hash[m.first] < m.second) return false;
    }
    return true;
}

标签:子串,right,hash,minlen,++,最小,enough,leetcode76,left
来源: https://blog.csdn.net/zhangjiaji111/article/details/120841564

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有