leetcode 76. 最小覆盖子串-java实现

题目所属分类

滑动窗口算法 属于双指针算法中的一个小范围
和这道题类似

leetcode 30. 串联所有单词的子串-java详细版本

可以对比着看

原题链接

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

注意:

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

代码案例:输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”

题解

在这里插入图片描述

class Solution {
    public String minWindow(String s, String t) {
         HashMap<Character,Integer> hs = new HashMap<Character,Integer>();//滑动窗口
         HashMap<Character,Integer> ht = new HashMap<Character,Integer>();//t的哈希
         for(int i = 0;i < t.length();i ++){
            ht.put(t.charAt(i),ht.getOrDefault(t.charAt(i), 0) + 1);
        }
        String ans = "";
        int cnt = 0 ;//统计有效字符的个数
        for(int i = 0 , j = 0; i < s.length() ; i ++){
            hs.put(s.charAt(i),hs.getOrDefault(s.charAt(i), 0) + 1);
            //有效字符 判断i是不是合法也算上
            if(ht.containsKey(s.charAt(i))&&hs.get(s.charAt(i)) <= ht.get(s.charAt(i))) cnt ++;
            //维护双指针 判断j是不是多余的
            while(j < i && (!ht.containsKey(s.charAt(j))||hs.get(s.charAt(j)) > ht.get(s.charAt(j)))){
                hs.put(s.charAt(j),hs.get(s.charAt(j)) - 1);
                j++;
            }
            //如果cnt==t的长度了,并且(res长度可以更新,或者res还没有赋值)
            if(cnt == t.length() && (ans.length() > (i-j+1 ) || ans.isEmpty() )){
                    ans = s.substring(j , i + 1) ;
            }
        }
        return ans ;
    }
}
class Solution {
    public String minWindow(String s, String t) {
        HashMap<Character,Integer> hs = new HashMap<Character,Integer>();//存s字符串的哈希表 滑动窗口
        HashMap<Character,Integer> ht = new HashMap<Character,Integer>();//存t字符串的哈希表
        for(char a : t.toCharArray() ) {//向哈希表ht中计数
            ht.put(a,ht.getOrDefault(a,0)+1);       
        }
        String res = "" ;
        int cnt = 0 ; 
        for(int i = 0, j = 0  ; i < s.length() ; i++){
            hs.put(s.charAt(i),hs.getOrDefault(s.charAt(i),0)+1);//向哈希表hs中计数
            //滑动窗口向右移动的时候 多加入一个字符 使得hs小与等于ht里面的字符个数 这样的叫做有效字符
         if(  hs.get(s.charAt(i)) <= ht.getOrDefault(s.charAt(i),0)) cnt ++;//有效计数加一
          // if( ht.containsKey(s.charAt(i)) && hs.get(s.charAt(i)) <= ht.get(s.charAt(i))) cnt ++;
            //开始滑动窗口左边的j移动 反过来的话 滑动窗口就需要移动了 记得此时是j向右移动
            while( j < i && hs.get(s.charAt(j)) > ht.getOrDefault(s.charAt(j),0)) {
                 hs.put( s.charAt(j) ,hs.get(s.charAt(j))-1);j++;
            }
           
               
            if(cnt == t.length()){
                if(res.isEmpty() || i - j + 1 < res.length() )
                 res =  s.substring(j , i + 1);
            }

        }
        return res ;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依嘫_吃代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值