【算法题解答·三】滑动窗口

【算法题解答·三】滑动窗口

接上文【算法方法总结·三】滑动窗口的一些技巧和注意事项


滑动窗口相关题目如下:

3.无重复字符的最长子串

  • 右边界 right 扩大,直到窗口中有重复字符
  • 窗口中有重复字符,则左边界 left 缩小
  • 使用 哈希表 来检查窗口中 是否有重复字符
// 先拓展右边界,再在循环中拓展左边界
class Solution {
    public int lengthOfLongestSubstring(String s) {
    	// 使用哈希表来检查窗口中是否有重复字符 
        Set<Character> set = new HashSet<>();
        char[] ss = s.toCharArray();
        int len = s.length();
        int res = 0;
        int left = 0; //左边界
        // 右边界
        for (int right = 0; right < len; right++) {
            char c = ss[right];
            // 因为子串是连续的,所以有重复就一直删
            while (set.contains(c)) {
                set.remove(ss[left]);
                left++; //拓展左边界
            }
            // 没重复了,添加
            set.add(c);
            res = Math.max(res, right - left + 1); //更新最大值
        }
        return res;
    }
}

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

  • 异位词,用 c1[26]c2[26] 来记录字符数
  • 此题为 固定长度滑动窗口
// 用c1[26]和c2[26]来记录字符数,滑动窗口的长度为 p 字符串的长度
// 用遍历1-26的方式来确定c1[]和c2[]对应字母是否
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        int[] c1 = new int[26], c2 = new int[26]; //记录字符数
        int n = s.length(), m = p.length();
        // 先记录 p 中的字符
        for (int i = 0; i < m; i++) {
            c2[p.charAt(i) - 'a']++;
        }
        // 固定长度的滑动窗口
        int left = 0; //左边界
        for (int right = 0; right < n; right++) {
            c1[s.charAt(right) - 'a']++;
            if (right - left + 1 > m) { //拓展左边界
                c1[s.charAt(left) - 'a']--;
                left++;
            }
            // 确认是异位词
            if (check(c1, c2)) {
                res.add(left); //首字符下标
            }
        }
        return res;
    }
    public boolean check(int[] c1, int[] c2) {
        for (int i = 0; i < 26; i++) {
            if (c1[i] != c2[i])
                return false;
        }
        return true;
    }
}

209.长度最小的子数组

  • 长度 最小 连续子数组,非常适合 滑动窗口 的方法
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0; // 窗口内的和
        int result = Integer.MAX_VALUE; // 记录最小长度
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right]; // sum < target时,一直向右扩大窗口
            while (sum >= target) { // sum >= target时,一直向左缩小窗口
                result = Math.min(result, right - left + 1);
                sum -= nums[left++]; // 向左缩小窗口
            }
        }
        if (result == Integer.MAX_VALUE) { // 不存在符合条件的子数组
            result = 0;
        }
        return result;
    }
}

算法题解答系列

【算法题解答·一】二分法
【算法题解答·二】双指针法
【算法题解答·三】滑动窗口
【算法题解答·四】字符串操作
【算法题解答·五】链表操作
【算法题解答·六】栈队列堆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值