算法——滑动窗口(day5)

209.长度最小的子数组 

209. 长度最小的子数组 - 力扣(LeetCode)

题目解析:

我们先从暴力破解的角度进行优化来过渡到滑动窗口的理论。

正常按照暴力就是先设一个sum来记录遍历指针right经过的数值若sum<target就让right继续往下遍历,直到sum>=target的时候记录长度持续到一轮结束后就移动left缩减范围进行新一轮的比较。最后就是挑出最小的len作为返回结果。

算法解析:

而滑动窗口算法就是在单调性这里对暴力算法作出优化。

在第一轮中当我们已经达到sum>=target的条件后就可以结束这一轮了,再继续往后遍历只会让长度更长(因为数组全为正整数).

而在第一轮结束后right也不用急着复位(与left共同指向),保持这个窗口。而窗口内的sum数值更新只需要sum-=2就行了。

滑动窗口流程图:只要没达到预期值,那我们就不断扩充窗口直到sum达成目标值。这时候先计算长度,然后开始缩小窗口(开始第二轮)。而无论是扩充窗口还是缩小窗口后面都需要判断,扩充完窗口后得看是继续扩充呢?还是先计数再缩小~缩小完窗口后得看是继续计数缩小呢?还是选择扩充。(因为无论扩窗还是缩窗sum都会发生改变,所以得进一步判断)

代码: 

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size(), sum = 0, ret = INT_MAX;
        for (int left = 0, right = 0; right < n; right++)
        {
            //扩窗口
            sum += nums[right];
            //判断是否继续扩充,若发现需要扩充,进入下一处循环
            //若发现已经扩充到目标值时,准备缩小
            while (sum >= target)
            {
                ret = min(ret, right - left + 1);//计数
                sum -= nums[left++];//缩窗口,然后再转回循环判断是否需要继续缩窗
            }
            //发现不需要继续缩窗了,进入循环进行再次扩充
        }
        return ret == INT_MAX ? 0 : ret;
    }
};

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

3. 无重复字符的最长子串 - 力扣(LeetCode)

题目解析:

这道题和上一道思路基本一致,先用暴力进行优化过渡到滑动窗口~

利用right指针遍历数组,每次遍历前都得利用哈希表判断一下,表内没有就添加进去,表内有那就停止遍历,先把重复项移出直到没有重复后最终才计算长度。

算法解析:

而滑动窗口算法就是对暴力解法的进一步优化~

在找到重复项后right不用复位,因为在第一轮中已经把遍历过的数都放在哈希表内了,而left与right又都为重复项,所以在新的一轮中只需要通过left来去除哈希表的其中一个重复项然后再移动就好了。 

滑动窗口流程:

无重复项——>扩充窗口(若仍无则继续扩充)(若有重复项,准备缩小窗口)

有重复项——>缩小窗口(仍有重复项,例如pwwkew继续缩小))(若无,准备扩充)

计算长度要再最后执行,不能放在缩小窗口循环内。这也是跟上一题的区别(上一题是通过缩小窗口来求长度最小,所以每一次缩小都有可能得到最小长度)(而本题是求最大连续长度,只需要在去除所有重复项后计算就行了)

代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.size();
        int ret = INT_MIN;
        int hash[128] = { 0 };//用数组模拟哈希表
        for (int left = 0, right = 0; right < n; right++)
        {
            //扩充窗口
            hash[s[right]]++;
            //判断,当扩充完后若无重复项,计算长度并进入下一循环扩充
            //当有重复项时,开始缩小窗口直到没有重复项
            while (hash[s[right]] > 1)
            {
                //缩小窗口
                hash[s[left++]]--;
            }
            ret = max(ret, right - left + 1);//没有重复项时计长度
            //计完长度后继续进入下一循环扩充
        }
        return ret == INT_MIN ? 0 : ret;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值