优选算法精品课--滑动窗口算法(一)

滑动窗口算法(一)

  • [(一) 长度最小的子数组](#(一) 长度最小的子数组)
    • [1.1 题目分析](#1.1 题目分析)
    • [1.2 算法原理](#1.2 算法原理)
    • [1.3 代码实现](#1.3 代码实现)
  • (二)无重复字符的最长子串
    • [2.1 题目分析](#2.1 题目分析)
    • [2.2 算法原理](#2.2 算法原理)
    • [2.3 代码实现](#2.3 代码实现)
  • [(三)最大连续1的个数 III](#(三)最大连续1的个数 III)
    • [3.1 题目分析](#3.1 题目分析)
    • [3.2 算法原理](#3.2 算法原理)
    • [3.3 代码实现](#3.3 代码实现)
  • [(四)将 x 减到 0 的最小操作数](#(四)将 x 减到 0 的最小操作数)
    • [4.1 题目分析](#4.1 题目分析)
    • [4.2 算法原理](#4.2 算法原理)
    • [4.3 代码实现](#4.3 代码实现)

(一) 长度最小的子数组

题目链接:

https://leetcode.cn/problems/minimum-size-subarray-sum/

1.1 题目分析

这道题要求我们在数组中找一个区间,这个区间的元素的和等于题目给出的target,如果找不到则返回-1.

1.2 算法原理

解法一:暴力遍历出所有的区间,然后找到最小区间

如果我们按照这种方法就需要两个循环才能解决问题,时间复杂度为O(n^2).效率非常的低

解法二:利用单调性 ,使用同向双指针(同向双指针就是我们的滑动窗口)

1.3 代码实现

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left=0,right=0,sum=0,len=INT_MAX;

        int n=nums.size();
        while(right<n)
        {
            sum+=nums[right];//入窗口
            while(sum>=target)//判断
            {
                len=min(len,right-left+1);//更新len
                sum-=nums[left++];//划出窗口
            }
            right++;//再入窗口
        }

        return len==INT_MAX?0:len;
    }
};

(二)无重复字符的最长子串

题目链接:

https://leetcode.cn/problems/longest-substring-without-repeating-characters/

2.1 题目分析

题目的意思就是让我们取找一个区间,在这个区间里的元素没有重复,返回区间的大小。

2.2 算法原理

解法一:暴力枚举+哈希表(去重)

解法二:根据规律,使用滑动窗口来解决问题

像上面两个常见的例子,我们的算法逻辑是将right所在的元素入哈希表,如果出现重复,我们就让left++,当重复消失,这时更新一下len即可。

2.3 代码实现

cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left=0,right=0,len=0;
        int a[128]={0};//用来观察是否有重复

        while(right<s.size())
        {
            a[s[right]]++;//入窗口
            while(a[s[right]]>1)
            {
                a[s[left++]]--;
            }
            len=max(len,right-left+1);
            right++;
        }

        return len;
    }
};

(三)最大连续1的个数 III

题目链接:

https://leetcode.cn/problems/max-consecutive-ones-iii/

3.1 题目分析

这个题的意思就是让我们找两个0的位置去翻转为1,使全部为1的区间长度最长。

3.2 算法原理

这道题需要我们转换一下思路,如果我们老老实实的按照题目中的那样先将一个0翻转为1,再找一个0翻转为1,那就太复杂了,那我们转换一下思路,我们是不是可以找一个区间,这个区间里0的个数为题目中的k,然后求这个区间最大的长度即可。

需要注意的是我们再入右区间的时候,如上图所示,这种情况下,left需要++,只要left位置还等于1,那区间一定在缩小,所以要是left当前的值不为0就直接跳过即可。

3.3 代码实现

cpp 复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int left=0,right=0,count0=0,len=0;

        int n=nums.size();
        while(right<n)
        {
            if(nums[right]==0)  count0++;//入窗口
            while(count0>k)//判断
            {
                if(nums[left]==1) left++;//跳过
                else
                {
                    left++;
                    count0--;//结束
                }
            }
            len=max(len,right-left+1);//更新len
            right++;
        }

        return len;
    }
};

(四)将 x 减到 0 的最小操作数

题目链接:

https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/

4.1 题目分析

这道题就是让我们在左右区间来删除元素,使题目中的x最后为0。

4.2 算法原理

这道题也需要我们转换一下思路,如果我们来按照题目中的方法来左右一个一个删除的话,情况太多了,所以我们可以来找反面,正所谓"正难则反"嘛,所以我们就去找中间的区间,让中间的区间元素和为数组总元素和与x之差相等,再用一次滑动窗口求解出这个区间即可。

4.3 代码实现

cpp 复制代码
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int sum=0;
        for(int i=0;i<nums.size();i++)
        {
            sum+=nums[i];
        }
        int target=sum-x;

        if(target<0)
            return -1;
            
        int left=0,right=0,len=-1,count=0;
        while(right<nums.size())
        {
            count+=nums[right];
            while(count>target)
            {
                count-=nums[left++];
            }
            if(count==target)
                len=max(len,right-left+1);
            right++;
        }

        if(len==-1)
            return len;
        else
            return nums.size()-len;
    }
};
相关推荐
幸运超级加倍~1 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
yannan201903131 小时前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法1 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR1 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
linsa_pursuer1 小时前
快乐数算法
算法·leetcode·职场和发展
小芒果_011 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
qq_434085901 小时前
Day 52 || 739. 每日温度 、 496.下一个更大元素 I 、503.下一个更大元素II
算法
Beau_Will1 小时前
ZISUOJ 2024算法基础公选课练习一(2)
算法
XuanRanDev1 小时前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
gkdpjj1 小时前
C++优选算法十 哈希表
c++·算法·散列表