ICode9

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

LeetCode 76.最小覆盖子串

2021-07-05 19:29:30  阅读:181  来源: 互联网

标签:子串 right 窗口 sum 76 need 滑动 LeetCode left


题目:

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

注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

思路:

  • 本题所采用方法为滑动窗口,即设置两个指针left和right来表示当前窗口的左右界限,我们可以设置一个need数组,索引代表字符,索引在数组中的值代表还需要几个当前字符才能符合t的标准
  • 第一步:每次先移动right指针,碰到一个值就让need[s.charAt(right)]--,如果当前字符存在于目标字符串t中,那么也让sum--,直到sum==0 ,此时说明当前滑动窗口已经包含了所有目标字符串t
  • 第二步:第一步走完之后,就该移动left指针了,因为刚才right指针走过的位置中可能存在不需要的字符,通过移动left指针可以缩小当前滑动窗口的范围,直到碰到第一个在字符串t中出现的字符,这时的一个最小滑动窗口区间就出现了,但他并不一定是最终结果,因为后面可能还会存在比当前滑动窗口区间还要小的情况
  • 第三步:将第二步找到的第一个存在于目标串t中的字符从need数组中剔除(need[s.charAt(left)]++,表示当前滑动窗口还需要这个字符),并继续移动right指针重复刚才的第一步,直到right指针走到s字符串的最后,这样整个字符串的最优结果就出现了

以下为代码+注释:

	public String minWindow(String s, String t) {
        // 滑动窗口
        // 首先设置一个need[]数组,索引为字符的int类型,数值代表需要几个该字符
        int[] need = new int[128];
        int slen = s.length();
        int tlen = t.length();
        // 先将目标字符串t遍历一遍,将需要的字符在need数组中更新相应的值
        // 这样如果need数组中的值都小于等于0了,就说明当前窗口已经将需要的东西包含完了,没有需要的字符了
        for(int i = 0; i < tlen; i++){
            need[t.charAt(i)]++;
        }
        // 第一步:设置两个指针,首先移动右指针,并维护一个sum表示需要的字母总和,
        // 每碰到一个需要的字符,就将need中对应字符的值--,并将sum--,如果sum为0,说明不需要字母了,当前滑动窗口已经包含t的所有字母
        // 第二步:这个时候就要移动左指针,因为左边区域可能有很多不需要的字母,我们需要将他们删除来求出最小的滑动窗口大小,并设置一个start
        // 第三步:根据start索引以及size大小截取并返回最终结果,size表示最小包含所有t中字母的滑动窗口大小,start代表该情况下滑动窗口的第一个索引位置
        int left = 0, right = 0, sum = tlen, size = Integer.MAX_VALUE, start = 0;
        while(right < slen){
            // 如果该字母恰好是需要的字母,就将sum--,也就是还需要查找的字母数量--
            if(need[s.charAt(right)] > 0){
                sum--;
            }
            // 不管该字母是否需要,都要将它对应的need数组--
            need[s.charAt(right)]--;
            // 如果sum为0,说明t中所有字母都包含了,这时就要移动左指针了
            if(sum == 0){
                while(left < right && need[s.charAt(left)] < 0){
                    need[s.charAt(left)]++;
                    left++;
                }
                // 走到这,说明走到了第一个need值为0的地方(因为不存在于t中的字母经过right指针向右移动时的--,他们的need对应值肯定是小于0的),也就是第一个在t中存在的字母
                // 那么就要将当前情况下的滑动窗口大小和size也就是记录大小作比较,如果这个更小,那么就进行更新
                if(right - left + 1 < size){
                    // 同时更新size,并将开始索引start置为第一个目标字母所在索引
                    size = right - left + 1;
                    start = left;
                }
                // 然后将第一个目标字母从华东窗口中剔除,也就是将该字母对应的need值加1,说明滑动窗口中还需要该字母,进行下一个新的滑动窗口的寻找
                need[s.charAt(left)]++;
                sum++;
                left++;
            }
            right++;
        }
        // 如果size为默认初始值,说明就没有符合条件的滑动窗口,返回空串,否则,返回以start索引开头的最小串
        return size == Integer.MAX_VALUE ? "" : s.substring(start, start + size);
    }

笔者也在不断学习,如有错误,欢迎指正!

标签:子串,right,窗口,sum,76,need,滑动,LeetCode,left
来源: https://blog.csdn.net/Riven__c/article/details/118495757

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

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

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

ICode9版权所有