leetcode算法基础 第五天 滑动窗口

438. 找到字符串中所有字母异位词

题目
这道题找所有字符串的异位词,异位词是指字符串所有字符的全排列组合,所以滑动窗口的大小是固定的,需要两个hashmap,一个记录当前窗口内的字符以及value值,另一个记录要找的字符串的字符以及value值。需要注意的点是,滑动窗口内左边界在移出时的字符对应的value值为1时,删除hashmap中的该值,若大于1则将value减1。通过遍历不断判断两个hashmap是否一致。

//使用hashmap 固定滑动窗口大小,先初始化一个滑动窗口,每次向右移动一位,判断是否符合要求
public List<Integer> findAnagrams(String s, String p) {
    List<Integer> res = new LinkedList<>();
    int m = s.length(), n = p.length();
    if (m < n) return res;
    Map<Character, Integer> s_map = new HashMap<>();
    Map<Character, Integer> p_map = new HashMap<>();
    for (int i = 0; i < n; i++) {  //初始化窗口以及目标字符串
        s_map.put(s.charAt(i), s_map.getOrDefault(s.charAt(i), 0) + 1);
        p_map.put(p.charAt(i), p_map.getOrDefault(p.charAt(i), 0) + 1);
    }
    if (s_map.equals(p_map)) res.add(0);
    for (int i = n; i < m ; i++) {
        if (s_map.get(s.charAt(i - n)) > 1){
            s_map.put(s.charAt(i - n), s_map.get(s.charAt(i - n)) - 1);
        } else {
            s_map.remove(s.charAt(i - n));
        }
        s_map.put(s.charAt(i), s_map.getOrDefault(s.charAt(i), 0) + 1); //左边界移出,右边界移进
        if (s_map.equals(p_map)) res.add(i - n + 1);
    }
    return res;
}

713. 乘积小于K的子数组

题目
这道题要找乘积小于 k 的连续的子数组的个数,所以不能用回溯的方法。
知道是滑动窗口,但是没写出来。看了大佬们的思路写了一遍,关键是要理解
r-l+1,以及为什么不会重复
每一次循环找的是以r为右边界的子数组,r一直在变,所以一定不重复
比如5,2,6此时满足条件,此时右边界为6,要找的数组就是[6],[6,2],[6,2,5]
每个长度的数组只有一个,相当于求这个l…r的闭区间长度
边界处理:当k为0或者1直接返回0
这样也保证了在收缩左边界时候不会越界,因为l收缩到r之后prod就为1了,一定小于k,会退出内层循环
此时表示没有合适的区间满足乘积小于k,此时l++之后l=r+1的,r-l+1也正好是0

public int numSubarrayProductLessThanK(int[] nums, int k) {
    if (k <= 1) return 0;
    int prod = 1, ans = 0, left = 0;
    for (int right = 0; right < nums.length; right++) {
        prod *= nums[right];
        while (prod >= k) prod /= nums[left++];
        ans += right - left + 1;
    }
    return ans;
}

209. 长度最小的子数组

题目
这道题就是最简单的滑动窗口的用法,首先右边界右移,直到满足要求,记录此时的窗口长度,然后左边界右移,只要不满足条件就停止右移,以此类推直到右边界达到数组最右端,且窗口满足条件。

public int minSubArrayLen(int target, int[] nums) {
    int re = Integer.MAX_VALUE;
    int sum = 0; int left = 0;
    for (int right = 0;right < nums.length; right++){
        sum += nums[right];
        if (sum >= target) {
            re = Math.min(re, right - left + 1);
            while (left <= right) {
                sum -= nums[left++];
                if (sum >= target) {
                    re = Math.min(re, right - left + 1);
                } else break;
            }
        }
    }
    return re == Integer.MAX_VALUE ? 0 : re;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值