zoukankan      html  css  js  c++  java
  • 【LeetCode-滑动窗口】最小覆盖子串

    题目描述

    给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
    示例:

    输入: S = "ADOBECODEBANC", T = "ABC"
    输出: "BANC"
    

    说明:

    • 如果 S 中不存这样的子串,则返回空字符串 ""。
    • 如果 S 中存在这样的子串,我们保证它是唯一的答案。

    题目链接: https://leetcode-cn.com/problems/minimum-window-substring/

    思路

    使用滑动窗口来做,使用两个指针 left 和 right 来标记窗口的大小,窗口大小为 right-left+1。left 和 right 初始化为 0,首先将 right 指向的元素加入窗口中并增加 right,直到窗口中包含 T 中所有元素,然后通过增加 left 来缩小窗口大小。算法具体过程如下:

    我们使用一个哈希表cnt来记录 T 中元素出现的个数。那么,对于一个字符 c ,如果 c 在 T 中出现了,则 cnt[c]>0;如果 c 没有在 T 中出现,则 cnt[c]==0。使用 left 和 right 来遍历字符串 S,假设当前 right 指向的字符为 c ,将 cnt[c]--,如果 c 在 T 中出现,那么现在 cnt[c]>=0(之所以会大于 0 是因为 T 中可能会包含重复字符),否则 cnt[c]<0。如果减一后 cnt[c]>=0,说明我们在 S 中找到了一个在 T 中出现的字符,则当前找到的字符长度 curLen++。如果 curLen==T.length(),说明我们现在滑动窗口中已经包含了 T 中的所有字符,则可以通过增加 left 来缩小滑动窗口的大小。将 cnt[s[left]]++,如果 s[left] 是 T 中的字符,则加一后的 cnt[s[left]]>0,将 left+1 后,滑动窗口中就不完全包含 T 中的所有字符了(少了一个),这时停止缩小窗口的大小,也就是停止增大 left。如果加一后的 cnt[s[left]]<0,则说明 s[left] 没有在 T 中出现,可以继续缩小窗口。

    循环结束的条件是 right>=S.length().

    具体代码如下:

    class Solution {
    public:
        string minWindow(string s, string t) {
            unordered_map<char, int> cnt;
            for(auto c:t) cnt[c]++;  // 统计 t 中字符出现的次数
    
            int left=0, right=0;
            int minLen=INT_MAX;
            int curLen=0;  // 当前在s中已经找到的字符个数
            string ans="";
            while(right<s.length()){
                cnt[s[right]]--;
                if(cnt[s[right]]>=0) curLen++;
    
                while(curLen==t.length()){
                    int windowSize=right-left+1; // 窗口大小
                    if(windowSize<minLen){  // 找到了更短的符合要求的字符串
                        minLen=windowSize;
                        ans = s.substr(left, windowSize);
                    }
                    cnt[s[left]]++;
                    if(cnt[s[left]]>0) curLen--; // 窗口中的字符不全
                    left++;
                }
                right++;
            }
            return ans; 
        }
    };
    
    • 时间复杂度:O(n)
      n 为 S 的长度。
    • 空间复杂度:O(n)

    参考

    https://leetcode-cn.com/problems/minimum-window-substring/solution/c-zuo-you-zhi-zhen-fa-xiang-jie-by-yizhe-shi/

  • 相关阅读:
    基础
    树梅派线程
    超声波
    电脑版微信双开多开
    子类能不能重写父类的构造方法
    window8taskost.exe一直占用cpu
    windows下rocketmq安装
    spring循环依赖问题
    线程池的种类
    并行和并发有什么区别?
  • 原文地址:https://www.cnblogs.com/flix/p/12944630.html
Copyright © 2011-2022 走看看