76.最小覆盖子串——学习笔记

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

注意

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案
    示例1
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A''B''C'

示例2

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

示例3

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

题目来源:力扣(LeetCode) 链接

解题模板(出自labuladong)

/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
    Map<Character, Integer> need = new HashMap<>();
    Map<Character, Integer> window = new HashMap<>();
    for (char c : t.toCharArray()) 
        need.put(c,need.getOrDefault(c,0)+1);
	int left = 0, right = 0;
	int valid = 0; 
	while (right < s.size()) {
    	// c 是将移入窗口的字符
   	 	char c = s.charAt(right);
    	// 右移窗口
    	right++;
    	// 进行窗口内数据的一系列更新
    	...

    	/*** debug 输出的位置 ***/
    	System.out.println("window: ["+left+","+ right+")");
    	/********************/
    
    	// 判断左侧窗口是否要收缩
    	while (window needs shrink) {
        	// d 是将移出窗口的字符
        	char d = s[left];
        	// 左移窗口
        	left++;
        	// 进行窗口内数据的一系列更新
        	...
    	}
	}
}

题解

class Solution {
    public String minWindow(String s, String t) {
        //定义一个map以键值对的方式存放t中的每一个字符以及对应的个数
        Map<Character, Integer> need = new HashMap<>();
        //定义一个map存放窗口中对应的字符和字符个数
        Map<Character, Integer> window = new HashMap<>();
        //把字符串t中的字符和对应的个数保存到map中
        for(char c : t.toCharArray()) {
            //getOrDefault(key,default)函数作用:
            //如果存在key,就返回对应的value,否则返回默认值
            need.put(c, need.getOrDefault(c, 0) + 1);
        }
        int left = 0;//定义左指针
        int right = 0;//定义右指针
        //count用来记录窗口中的字符个数是否满足需要,如果有一个字符满足,count++
        int count = 0;
        int start = 0;//用来记录满足要求的子串的起始位置
        //len用来记录满足要求的子串的长度,每次都与len比较,选出来最小的
        int len = Interget.MAX_VALUE;
        while (right < s.length()) { //更新窗口
            char c = s.toCharAt(right);
            right++;
            if (need.containsKey(c)) { //判断取出的字符是否是need需要的
                //如果需要,就把该字符和个数放入到window中
                window.put(c, need.getOrDefault(c, 0) + 1);
                //如果window中的c字符个数满足要求,就记录下来
                if (need.get(c) == window.get(c)) {
                    count++;
                }
            }
            //count == need.size()说明此时子串满足要求,所以开始收缩窗口
            while (count == need.size()) {
                //如果此时子串长度更小就更新len,并且更新子串的起始位置
                if (right - left < len) {
                    len = right - left;
                    start = left;
                }
                //从子串最左侧开始取出字符(收缩窗口)
                char d = s.toCharAt(left);
                left++;
                //判断need中是否存在该字符
                if (need.containsKey(d)) {
                    //先判断此时need中该字符的数量是否和window中的相等,相等就count--
                    if (need.get(d) == window.get(d)) {
                        count--;
                    }
                    //每次都要先判断再把window中对应的字符数量减1
                    window.put(d, window.get(d) - 1);
                }
            }
        }
        //如果len不等于原来的值说明找到了,就返回对应子串,否则返回空串
        return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
    }
}
posted @   会飞的笨笨  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示