滑动窗口技术

leetcode3.209等题目都是滑动窗口解决的。
都是一种在数组这种数据结构中寻找最长,最短的情况,咋一看刚开始想着动态规划可能是这种题目的解法。
但是适用于动态规划的题目的解法不适用于这种类型的题。毕竟动态规划解决的是含有1.最优子结构性质。2.重叠子问题。3.无后效性等情况。
但是这都是在数组中有多个可行解,都是在满足一定条件下把当前的不确定的结果(可能是最大或者最小的情况给保存下来),不断去寻找,直到其中左指针到达数组的末尾,结束寻找。

写代码之前的特殊情况的考虑真的重要。考虑越清晰,越好写。
附上错误代码,leetcode438题目

public List<Integer> findAnagrams(String s, String p) {
        List<Integer> list = new ArrayList<>();
        if (s == null)
            return list;
        //Map<Character, Integer> map = new HashMap<>();
        int[] number = new int[26];
        char[] chars = p.toCharArray();
        char[] nums = s.toCharArray();
        int len = chars.length;
        for (int i = 0; i < len; i++) {
            //  map.put(chars[i],0);
        }
        int l = 0, r = -1;
        int charlen = p.length();
        return null;
    }
/*
        //滑动
        while(l < nums.length){

            if(r+1 < nums.length && forMap(map) < charlen){
                //移动r++
                if(map.containsKey(nums[++r])){
                    //包含,就正常操作
                   if(map.get(nums[r]) != 1) {
                       map.put(nums[r], 1);
                    }else{

                        l++;

                    }
                }else{
                    //不包含,非正常操作就好了
                    //l都置下一位,r置当前不符合的位置
                    l = r + 1;
                    //同时清空map中所有的值
                    clear(map);
                }

            }else{
                //对左指针l--,从map去掉l对应的1
                if(map.containsKey(nums[l]))
                    map.put(nums[l],0);
                //都要l++;
                l++;
            }

            if(forMap(map) == charlen){
               list.add(l);
            }
        }

        return list;
    }

    public int forMap(Map<Character,Integer> map){

        int sum = 0;
        for(Integer a:map.values()){
            sum += a;
        }
        return sum;
    }

    public void clear(Map<Character,Integer> map){

       for(Map.Entry<Character,Integer> entry:map.entrySet()){
           map.put(entry.getKey(),0);
       }

    }

 */

感觉自己陷入了一种误区,误区在哪呢?在不懂滑动窗口的本质。应该去思考这个本质

  • 1.什么情况下右移
  • 2.什么情况下左移
  • 3.满足条件下应该做什么操作。

这3者又都是根据不同的题目做出不同的要求。根据实际情况的变化而变化。
其次在438题目中,我很操蛋的去维护一个Map,其实这里根据题目情况只有26个字符,根本不用用map,所以得到一个感受就是能尽量简单的数据结构解决的问题,尽量不要用复杂的数据结构,复杂的数据结构操作起来也花时间,
大神用数组来保存下来,用 res[chars[i]-‘a’] += 1; 每一个字符减去’a’即可,这是小技巧,求自己记住了。 之前的思路类似,就是当前符合就操作Map,维护这个map,为啥不用2个数组呢? s字符串用一个,p字符串也用一个,用s数组去不断判断p数组,满足与否。

leetcode438题
1.什么情况下右移,即每次不管找到与否,都右移,并且加入s数组中。
2.啥时候左移呢? 即当r-l+1>p.length()这个条件,就进行s数组 s[chars[l++]-‘a’]–;减去1同时l++,这样设立的条件,特别符合题目给出的情况下,符合所有的不满足情况,都进行滑动窗口的左边界移动。
3.当题目满足就将list.add即可。

正确的大神思路:

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        
        List<Integer> res = new ArrayList<>();
        
        if(s.length() < p.length())
            return res;
        
        char[] charp = p.toCharArray();
        char[] chars = s.toCharArray();
        int[] res_p = new int[26];
        
        for(char c:charp)
            res_p[c-'a'] += 1; 
        
        int[] res_s = new int[26];
        int l = 0,r = -1;
        while(r+1<s.length()){

            r++;
            
            res_s[chars[r]-'a'] ++;
            
            if(r-l+1>p.length())
                res_s[chars[l++]-'a']--;
            
            if(r-l+1 == p.length() && same(res_s,res_p))
                res.add(l);
            
        }
        
        return res;
    }
    
    public boolean same(int[] res_s,int[] res_p){
        
            for(int i=0;i<26;i++){
                
                if(res_s[i]!=res_p[i])
                    return false;
                
            }
            return true;
    }
}

发散一下:即如果当前数组中,寻找同位数组p在s中。同样也能用这个思路。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值