算法--滑动窗口

1. 尽可能使字符串相等

https://leetcode-cn.com/problems/get-equal-substrings-within-budget/

给你两个长度相同的字符串,s 和 t。

将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。

用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。

如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。

如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。

思路: 求解两个字符串相应位置的ASCII值查的绝对值数组,则本题转换为求解某一个数组中和小于某一值的最长连续子数组。

public int equalSubstring(String s, String t, int maxCost) {
        int n = s.length();
        int[] num = new int[n];
        for (int i=0; i<n; i++) {
            num[i] = Math.abs(s.charAt(i)-t.charAt(i));
        }
        int maxL = 0;
        int start = 0;
        int end = 0;
        int sum = 0;
        while (end < n) {
            sum += num[end];
            while (sum > maxCost) {
                sum -= num[start];
                start++;
            }
            maxL = Math.max(maxL, end - start + 1);
            end++;
        }
        return maxL;
    }

维护两个指针start,end, end不断向前探索,当end处于某一位置时,考虑此时start位置,区间start-end中组成的滑动窗口中数据是否符合题意,如果不符合,则移动start位置,使其符合,找到符合问题的解之后,记录该解。然后移动end,继续下一个位置的探索。

2. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

求某一数组中和大于某一值的最短连续子数组

 public int minSubArrayLen(int target, int[] nums) {
        int start = 0;
        int end = 0;
        int sum = 0;
        int minL = Integer.MAX_VALUE;
        while (end < nums.length) {
            sum += nums[end];
            while (sum >= target) {
                minL = Math.min(minL, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return minL == Integer.MAX_VALUE ? 0 : minL;
    }

3. 最大连续1的个数 III

给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。返回仅包含 1 的最长(连续)子数组的长度。

求解数组中零的个数小于某一值的最长连续子数组

 public int longestOnes(int[] A, int K) {
        int start = 0;
        int end = 0;
        int lSum = 0;
        int rSum = 0;
        int maxL = 0;
        while (end < A.length) {
            rSum += (1 - A[end]);
            while (lSum + K < rSum) {
                lSum += (1 - A[start]);
                start++;
            }
            maxL = Math.max(maxL, end - start + 1);
            end++;
        }
        return maxL;
    }

滑动窗口总结

1.本质上来说,滑窗是双指针,一根指针指向左端点,一根指针指向右端点。以右指针作为驱动,拖着左指针向前走。右指针每次只移动一步,而左指针在内部 while 循环中每次可能移动多步。右指针是主动前移,探索未知的新区域;左指针是被迫移动,负责寻找满足题意的区间。
2.右指针移动可以表示扩张窗口,左指针移动表示缩小窗口。
3.如果当前元素满足题目要求时,可以挪动右指针尝试更优解,并且更新需要记录的变量(元素,元素个数++等)
4.如果当前窗口内的元素不满足条件,可以挪动左指针尝试调整,并且更新需要记录的变量(元素,元素个数--等)
通过以上步骤窗口就开始“滑动”起来,在滑动过程中,要记得及时更新答案。一般为求最大或最小。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值