Java LeetCode 76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
示例 2:
输入:s = “a”, t = “a”
输出:"a"

这题需要用滑动窗口的思想来解决,滑动窗口的固定思维大致就是这样,

/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
    // 字符需要出现的次数
    Map<Character, Integer> need = new HashMap<Character, Integer>();
    // 滑动窗口中字符出现的次数
    Map<Character, Integer> window = new HashMap<Character, Integer>();
    
    for (char c : t.toCharArray()) 
    	needs.put(ch, needs.getOrDefault(ch, 0)+1);
    
    int left = 0, right = 0;
    int valid = 0; 
    while (right < s.size()) {
        // c 是将移入窗口的字符
        char c = s.charAt(right);
        // 如果满足条件就将 c移入窗口中,并进行窗口内数据的一系列更新
        if(...)
        	...
        // 右移窗口
        right++;
        

        /*** debug 输出的位置 ***/
        System.out.println("window: ["+left+", "+right+")\n");
        /********************/
        
        // 判断左侧窗口是否要收缩
        while (window needs shrink) {
            // d 是将移出窗口的字符
            char d = s.charAt(left);
            // 如果满足一定条件,进行窗口内数据的一系列更新,使得退出这个 while循环
            if(...)
            	...
            // 左移窗口
            left++;
        }
    }
}

如下可以套公式结题
题里需要特别注意的是
if(dict[c]>0&&dict[c]>=window[c])
这段代码,count–或者count++都需要保证这个条件,而不是单单dict[c]>0,因为如果是字符串是AABC,t是ABC,这种情况,字符串把最左边元素删除之后,字符串依然包含ABC,count依然是保持原样,而不是需要减一,这个需要非常非常注意

class Solution {
    public String minWindow(String s, String t) {
    	//特殊情况处理
        if(s==null||t==null||s.length()<t.length()){
            return "";
        }
        int window[] = new int[128];//定义窗口
        int dict[] = new int[128];//定义字典,记录t里每个字符
        int left=0,right=0;//left定义窗口左边界,right定义窗口右边界
        int count=0;//用来判断当前窗口是否含有t字符串每个元素
        String res="";//用来返回值
        int min=s.length()+1;//定义长度
        for(int i=0;i<t.length();i++){//先把t字符串每个元素放入dict字段中记录
            dict[t.charAt(i)]++;//通过ASCII码来存储,比如a字符对应的数字就是97,z对应的就是122,数组这个位置上是1就表示有1个该字母,2就是2个
        }
        while(right<s.length()){//开始滑动窗口
            char ch = s.charAt(right);
            window[ch]++;//把这个字符记录到窗口里
            right++;//窗口右移
            if(dict[ch]!=0&&dict[ch]>=window[ch]){//如果字典里有窗口右边的元素,则表示找到了t里一个字符,继续往后找
                count++;//用来记录找到了几个t里面的元素
            }
            while(count==t.length()){//当找全了所有t里的元素,这时候需要减小窗口找最小包含t元素的窗口
                char c = s.charAt(left);
                if(dict[c]>0&&dict[c]>=window[c]){
                    count--;//如果消失的是t里的元素,count--表示窗口又不包含t所有的元素了
                    if(right-left<min){//计算是否是最小窗口
                        min=right-left;
                        res=s.substring(left,right);
                    }
                }
                window[c]--;//窗口移除最左元素
                left++;//窗口左侧缩减
            }
        }
        return res;
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值