leetcode记录-76-最小覆盖子串-双指针

76.最小覆盖子串

在这里插入图片描述

思路

错误思路记录(自己记录,不要看):以t的长度作为初始区间长度,每个长度从头开始切子串,一直到末尾,因为从最小长度开始,如果找到满足条件的子串,即退出循环并return,找不到就区间长度加1,然后从头开始。对于“满足条件——统计子串中t中每个字符的个数”,写了统计String中某个字符出现个数的函数,对于子串中每个字符,如果其数目小于子串的数目,结束循环,区间步进。这种方法暴力搜索,时间复杂度太高,对于很长的字符串会报错——超出时间限制

  1. 滑动窗口的本质是:在滑动窗口类型的问题中都会有两个指针,一个用于「延伸」现有窗口的 rr 指针,和一个用于「收缩」窗口的 ll 指针。一个静止一个滑动。
  2. 题解思路:初始左右指针都在0下标处,首先右指针r向前步进,直到l和r之间的子串包含了t的所有字符,然后l向前步进,寻找目前r下的最优子串,当去掉l当前字符会导致不满足包含条件时,这个子串即当前r下的最优子串,将其记录。然后l不动,r继续步进,重复上诉操作,此时r下的最优子串长度若比之前的小,更新最优子串。—— 记录字符出现数使用128长度的int数组,下标指的字符的ASCII码(一共128个字符,其ASCII码为0-127)

代码

  1. 代码
class Solution {
    public String minWindow(String s, String t) {
        if (s.length()==0||t.length()==0) return "";
        int l=0 , r=0 , total=t.length() ,start=0 ,size=Integer.MAX_VALUE;
        int[] need = new int[128];
        for (int i = 0; i < t.length(); i++) {
            need[t.charAt(i)]++;
        }
        while(r<s.length()){
            if(need[s.charAt(r)]>0)
                total--;
            need[s.charAt(r)]--;
            if (total==0){
                while (need[s.charAt(l)]<0){
                    need[s.charAt(l)]++;
                    l++;
                }
                if (r-l+1<size){
                    size=r-l+1;
                    start=l;
                }
                need[s.charAt(l)]++;
                l++;
                total++;
            }
            r++;
        }
        if (size!=Integer.MAX_VALUE) return s.substring(start,start+size);
        else return "";
    }
}
  1. 代码思路:
    ①初始即可判断返回值的条件要首先列出:本题当s或者t长度为0时返回""
    ②然后声明变量:本题变量包括左指针l、右指针r、int数组need[]存储t中每个字符还需要几个(ASCII码为0-127)、一个total存储子区间一共还差几个字符、start存储目前最优区间开始下标、size存储目前最优区间的长度(初始长度设为最大int值)
    ③右指针一直在向前步进,每次新的r【1】先判断是不是需要的,需要的话total更新,然后条件判断外部更新need数组(因为不管是不是需要,都要一样的操作:更新need;而需要的话有不同的操作:更新total)【2】然后因为新的r更新了total,此时判断,当total为0时证明右指针满足区间包含所有字符,这时要【短暂停留,步进左指针】,当当前字符的need中值为负,就更新need值然后步进,循环停止时当前字符need值为0,不可以再+1,这时找到了当前r下的最优l,需要更新最优区间(当前区间比存储的size小的话,证明更优,更新start和size),因为需要继续步进进行,当前条件下,更新l的need,更新total(因为减少了一个必需字符),然后l步进一个【3】不管是有没有短暂停留,r正常步进,直到到边界
    ④如果size还为初始值就返回"",否则返回当前start到start+size的子串(substring为左闭右开)

技巧和总结

  1. 滑动区间的意思不是一个区间整体左右滑,而是左右指针滑动,区间大小改变,以寻找满足条件的。
  2. 思路一定要梳理好,每一种情况都考虑,而对于复杂的循环,放在大局思考。如本题,如果每次寻找到r,然后更新l,然后再更新r,就不知道怎么循环,但是整体来看,r一直在从0到末尾的路上,只不过有一个r恰好满足让l步进的条件,在其循环体里直接l处理完,r继续步进(只是短暂停留)。
  3. 需要一个很大的初始值:int size=Integer.MAX_VALUE;
  4. 初始可以判断排除的条件,开始之前直接处理了,如本题字符串为空的条件。
  5. subString为左闭右开。
  6. 需要记录字符出现个数这种,均可以参考本题处理方法,采用128长度的int数组,每一个下标代表一个字符,而a[‘s’]代表’s’的ASCII码为下标元素。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值