滑动窗口算法

本文介绍了一种寻找包含特定字符集的最短子串的高效算法。通过使用滑动窗口的方法,结合哈希表记录目标字符及其出现次数,实现了快速定位及验证。算法详细步骤包括初始化窗口边界、更新目标字符计数以及优化窗口大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.我们设定有一排球,代号不知道,用x表示

2,我们可以通过盒子可以观察到球真正的代号,比如

3.如果我们要在这排球里找到包含代号1,2的两个球的最短的球串,

 4、现在我们回到第2步,可以发现第一个球是1,因为盒子允许向左或向右伸缩,所以先向左扩,发现第二个球是3,此时盒子里的球是1,3,不包含1,2.

 

 5,我们继续向左扩,发现第三个球是2 。此时盒子里是1,3,2,包含1,2,所以这个盒子里的球串符合要求,记下来。

 6.接下来我们把盒子向左 缩,看一下少了一个球,是否还包含1,2,如果包含,那就找到了一个符合题目要求的更短球串,显然盒子里只有2,3,不符合要求。

 7.我们继续把盒子向左扩大,看能不能找到符合要求的球串,显然,此时球盒里包含1,2,3,有包含1,2,所以此球串符合题目要求。那么接下来我们重复第六步,把盒子向左缩,看能不能找到一个符合题目要求的更短球串。

 8.把盒子向左缩,盒子里包含1,2,找到了一个符合题目要求的更短球串。

9,重复第七步操作,每次找到符合要求的球串时,把盒子向左缩小,看能不能让子串变更短时也符合题目要求(包含1,2),如果不能,则把盒子向左扩大,纳入更多未知的球,让盒子里的球来满足题目要求(包含1,2球)。这里面有两个过程,一个扩是为了找到,一个缩是为了优化。

代码如下

最小覆盖子串(题意 :给定一个字符串S和T,找出S中包含T所有字符的最小子串。

注意:题目中只说明包含T中所有字符,顺序任意。例,S = “ADOBECODEBANC”,T = “ABC”,则满足题意的最小子串为“BANC”。当没有满足题意的子串时返回空字符串。)

public String minWindow(String s, String t) {//s相当于一排未知代号x的球,t相当要求包含的1,2球
        Map<Character,Integer> need = new HashMap<>();
        Map<Character,Integer> window = new HashMap<>();
        for(Character c : t.toCharArray()){
//把t记入need,并且根据代号记录该代号球的数量
            need.put(c,need.getOrDefault(c,0) + 1);
        }
        int start = 0,left = 0,right = 0,len = Integer.MAX_VALUE,valid = 0;
        while(right < s.length()){
//设置盒子向左扩不得超过这排球的长度
        
            char c = s.charAt(right);
            
            right++;
//盒子向左扩大
            
            if(need.containsKey(c)){//向左扩后新增的那个球,如果是t里面的,也就是1,2球里面的
                window.put(c,window.getOrDefault(c,0)+1);//把这个球的记下,并且代号数量加1
                if(window.get(c).equals(need.get(c))){

                     valid++;

//!注意,如果两个记录的相同代号数量相当,那么                                                           

//valid+1.因为need,也就是记录t的,里面的球代号的数量

 //是不变,但是window,也就是记录s中每个包含于t的新增球代                                                       //号的数量,数量每次都增加一,一旦超过need里面代                                                    

  //号相同球的数量,那么是不会再令need+1的,只有等于才会。这                                                //保证 了valid最大只能和need的长度相等
                                                                  
                }
            }

            //判断窗口是否要收缩
            while(valid == need.size()){//一旦相等了,就说明符合题目要求了,相当于包含1,2了
               
                if(right - left < len){//这里到下面的操作都是符合题目要求后,盒子向左收缩来看有无                                                 //更优解的操作,这步是记录盒子的长度和位置
                    len = right - left;
                    start = left;
                }

               
                char k = s.charAt(left);//先记录盒子向左收缩后,丢弃出盒子的那个球的信息
                left++;                 //向左缩
                if(need.containsKey(k)){//处理之前丢弃的那个球
                    if(need.get(k).equals(window.get(k))){
                        valid--;
                    }
                    window.put(k,window.getOrDefault(k,0)-1);
                }
            }
        }
        return len == Integer.MAX_VALUE ? "" : s.substring(start,start+len);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值