代码随想录刷题攻略---数组3--滑动窗口

题例:

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

此题的暴力解法是双层遍历,即O(n^2)的时间复杂度。这里提出一种O(n)的方法,即滑动窗口。

滑动窗口

滑动窗口使用两个移动指针,指针范围内的子数组就是一个窗口;不断调整窗口的大小和位置,使窗口内的子数组符合我们的要求,就是滑动窗口的使用目的。

在此题中,我们的窗口初始大小为 1 ,窗口的左边界和右边界都指向nums[0]。此时窗口内的总值sum = nums[0],在总值没有达到target之前,我们不断地将有窗口向右移动,更新sum。若某一时刻窗口内的sum == target,那么返回窗口的大小即可。

若窗口内的sum  >  target,说明此时以左边界起始的窗口 不能达到要求,我们将左窗口向右边,即下一个元素移动,更新窗口的左边界(此时要把原本左窗口的值从sum中减去)。

code:

 


扩展题:

这道题的思路也比较清晰,窗口的右边界向右扩展,记此时水果数量(即窗口的长度)。若此时窗口内的元素种类超过2种,左边界就要向右收缩,知道窗口内的水果种类为2为止,比较两种情况下水果数量谁更多。

这题的难点在于记录窗口内的水果种类,用unordered-map来记录会比较方便(若用数组或者变量来记录会分不清哪个种类先摘哪个后摘)

code:

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int total=INT_MIN;
        int i=0;
        int j=0;
        //int type=1;
        //int temp=0;
        unordered_map<int, int> cnt; //种类->数量,方便遍历时判断这个种类是否已经存在
        for(j;j<fruits.size();++j)
        {
            ++cnt[fruits[j]];//该种类的水果数量++
            while(cnt.size() > 2)//种类满了后,将同种类退出
            {
                // --cnt[fruits[i]];
                // i++;
                //为了指定代表i指向的水果种类,必须用指针来指向这个键值对
                auto it = cnt.find(fruits[i]);//指针指向相应键的键值对
                -- it -> second;
                if(it -> second == 0)
                cnt.erase(it);
                i++;
            }
            total = total > j-i+1 ? total : j-i+1;//权值为1,则窗口长度就是数量
        }
        
        return total;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值