ICode9

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

LeetCode-76. 最小覆盖子串

2022-01-12 11:04:23  阅读:141  来源: 互联网

标签:子串 字符 cnt 窗口 ++ 76 字符串 滑动 LeetCode


题目来源

76. 最小覆盖子串

题目详情

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"

示例 2:

输入: s = "a", t = "a"
输出: "a"

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:

  • 1 <= s.length, t.length <= 105
  • st 由英文字母组成

进阶: 你能设计一个在 o(n) 时间内解决此问题的算法吗?

题解分析

解法一:双指针法

滑动窗口的思想:

i,j表示滑动窗口的左边界和右边界,通过改变i,j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j-i+1,这些长度中的最小值就是要求的结果。

步骤一

不断增加j使滑动窗口增大,直到窗口包含了T的所有元素

步骤二

不断增加i使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度减小,直到碰到一个必须包含的元素,这个时候不能再扔了,再扔就不满足条件了,记录此时滑动窗口的长度,并保存最小值

步骤三

i再增加一个位置,这个时候滑动窗口肯定不满足条件了,那么继续从步骤一开始执行,寻找新的满足条件的滑动窗口,如此反复,直到j超出了字符串S范围。

如何判断滑动窗口包含了T的所有元素?

  1. 对于如何判断滑动窗口中包含所有元素,我们可以使用一个整数数组,类似于以前做过的字符串所有相同的字母异位词问题字母异位词分组问题
  2. 这里可以优化的一个地方就是,如果单纯使用cnts数组计数每个字符出现的次数,那么在判断的时候每次都需要判断数组中所有元素的数量都小于等于0时,表示当前滑动窗口不再需要任何元素。
  3. 具体地,我们可以再使用一个计数指针cnt表示目标串中总共需要计数的字符数,并在滑动窗口的过程中维护该变量。最后,只需要判断cnt是否为0即可。
class Solution {
    public String minWindow(String s, String t) {
        int n = t.length();
        int cnt = n;// 记录目标串所有字符出现的总次数
        int l=0, r=0;// 双指针的左右边界
        int[] cnts = new int[128];// 记录某个英文字母(大小写字母最大ascii码为126)出现的次数
        for(int i=0; i<n; i++){// 遍历t字符串,记录每个字符的出现次数
            cnts[t.charAt(i)]++;
        }
        int minsize = Integer.MAX_VALUE;// 满足条件的最小窗口
        String ans = "";
        while(r < s.length()){// 遍历s字符串
            char ch = s.charAt(r);
            if(cnts[ch] > 0){// 需要该字符
                cnt--;
            }
            cnts[ch]--;// 计数该字符,所需字符数量减一
            if(cnt == 0){// 窗口中已经包含目标串中的所有字符
                while(l < r && cnts[s.charAt(l)] < 0){// 不断向右移动左指针,但始终保持窗口中含有目标串的所有字符
                    cnts[s.charAt(l)]++;// 释放左指针所在字符
                    l++;
                }
                if(r - l + 1 < minsize){
                    minsize = r - l + 1;
                    ans = s.substring(l, r + 1);
                }
                // 左指针再向右移动一个位置,那么窗口中肯定不满足条件
                cnts[s.charAt(l)]++;
                l++;
                cnt++;
            }
            r++;// 右指针右移
        }
        return ans;
    }
}

结果展示

image

标签:子串,字符,cnt,窗口,++,76,字符串,滑动,LeetCode
来源: https://www.cnblogs.com/GarrettWale/p/15791585.html

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

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

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

ICode9版权所有