【摸鱼摸鱼】滑动窗口(一)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、定义

 滑动窗口定义为在指定在给定窗口大下的数组或字符串上进行操作,从而将嵌套循环降为单循环,降低时间复杂度。

二、解题套路

 滑动窗口的基本套路可以归结为:在给定的数组/字符串中,要求找到连续子空间使得某个条件成立。求解这类问题的方法通常都是先右移右边框架,直到满足条件之后,左边框架开始左移,直到条件不成立,并且每当找到一个符合条件的状态就更新一次解,经过一轮迭代之后就可以找到最优解。

三、Leetcode easy

1、存在重复元素 II

问题描述
在这里插入图片描述
解题思路:
 滑动窗口的大小在[1,k]之间,首先使用map容器来记录left、right所指的元素在滑动窗口中的出现次数,如果次数超过1,则说明有元素满足条件直接返回true;否则,如果区间小于k,则right右移,否则left右移,当遍历完整个数组时,也就可以得到最后的结果。
 在看了评论之后发现解题思路还有很多,比如使用长度为k的哈希表,当长度超过k的时候就删除最早添加的数字等等,基本思路大概一致。

解题代码:

class Solution {
public:
    map<int, int>number;
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        if(nums.size()==1)
            return false;
        int left = 0;
        int right = left + 1;
        if (number.find(nums[left]) != number.end())
            number[nums[left]]++;
        else
            number[nums[left]] = 1;
        if (number.find(nums[right]) != number.end())
            number[nums[right]]++;
        else
            number[nums[right]] = 1;
        while (left < nums.size() && right < nums.size())
        {
            
            if (number[nums[right]] > 1)
                return true;
            else if (right - left < k)
            {
                right++;
                if (right < nums.size())
                {
                    if (number.find(nums[right]) != number.end())
                        number[nums[right]]++;
                    else
                        number[nums[right]] = 1;
                }
            }
            else
            {
                number[nums[left]]--;
                left++;
                if (number[nums[left]] > 1)
                    return true;
            }
        }
        return false;
    }
};

运行结果:
在这里插入图片描述

2、

问题描述
在这里插入图片描述

解题思路:
 很典型的滑动窗口的题目,将窗口的大小控制在k个,每次只需要对边缘进行加、减的操作,注意结果返回值类型为double,因此需要注意小数除法。

解题代码:

class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        int left = 0;
        int right = left + k-1;
        int sum =0;
        for (int i = left; i <= right; i++)
            sum += nums[i];
        int maxres = sum;
        while (right<nums.size())
        {
            maxres = max(maxres, sum);
            sum -= nums[left];
            left++;
            right++;
            if(right==nums.size())
                break;
            sum += nums[right];
            //cout << sum << endl;
        }
        return (double)maxres / k;
    }
};

运行结果:
在这里插入图片描述

3、

问题描述
在这里插入图片描述

解题思路:
 这道题目比较简单,因为直接限制了子字符串的长度为3,并且要求连续,所以可以每次只截取滑动窗口为3的子字符串主意比较即可得到最终的数据。

解题代码:

class Solution {
public:
    int countGoodSubstrings(string s) {
        int res = 0;
        for (int i = 0; i <= s.size() - 3; i++)
        {
            string tmp = s.substr(i, 3);
            if(tmp.size()<3)
                break;
            if (tmp[0] != tmp[1] && tmp[1] != tmp[2] && tmp[0] != tmp[2])
                res++;
        }
        return res;
    }
};

运行结果:
在这里插入图片描述

总结

 滑动窗口如果用得好还是可以节省很大时间消耗的,一开始上手做简单题感觉不会很难,明天开始接触中等和困难的题目。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值