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

滑动窗口算法(一)

  • [(一) 长度最小的子数组](#(一) 长度最小的子数组)
    • [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;
    }
};
相关推荐
thesky12345613 分钟前
活着就好20241226
学习·算法
td爆米花26 分钟前
C#冒泡排序
数据结构·算法·排序算法
chenziang11 小时前
leetcode hot100
算法·leetcode·职场和发展
执着的小火车1 小时前
02-18.python入门基础一基础算法
数据结构·python·算法·排序算法
梦茹^_^1 小时前
排序算法(系列)
数据结构·python·算法·排序算法·希尔排序·基数排序·计数排序和桶排序
花开盛夏^.^1 小时前
Timsort算法
数据结构·算法·排序算法
code monkey.1 小时前
【排序算法】—— 计数排序
c++·算法·排序算法
云青山水林1 小时前
2024.12.21 周六
c++·算法·贪心算法
chenziang11 小时前
leetcode hot二叉树的层序遍历
数据结构·算法
pianmian11 小时前
完全平方数
数据结构·算法