【优选算法】——滑动窗口(上篇)!

目录

1、长度最小的子数组

2、无重复字符的最长子串

3、最大连续一的个数

4、将x见到0的最小操作数 

​编辑

5、完结散花


1、长度最小的子数组

题目链接icon-default.png?t=O83Ahttps://leetcode.cn/problems/minimum-size-subarray-sum/description/

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 

子数组

  [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度 如果不存在符合条件的子数组,返回  0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

解题思路:

1、我们首先想到的一定是暴力枚举所有的子数组,记录最小的长度即可解决问题。但这种解法必然超时。所以我们要对其进行优化。

2、当我们固定一端left,用right去枚举时,当right恰好走到大于等于target的位置。这时候right其实就没有必要继续往后走了,因为后面的长度都大于此时的长度!

3、那我们就更换固定点left,那这时候right也没有必要傻乎乎的回到固定点重新枚举。我们先让sum-=nums[left] ,left++(出窗口)。继续判断是否满足条件即可。

解题代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int len=nums.size();
        int left=0,right=0,sum=0,ret=INT_MAX;
        while(right<len)
        {
            //进窗口
            sum+=nums[right];
            while(left<len&&sum>=target)
            {
                //更新结果
                ret=min(ret,right-left+1);
                //出窗口
                sum-=nums[left++];
            }
            right++;
        }
        return ret==INT_MAX?0:ret;    
    }
};

2、无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 

子串

 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

 

 解题代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.size();
        int hash[128]={0};
        int ret=0;
        for(int left=0,right=0;right<len;right++)
        {
            //进窗口
            hash[s[right]]++;
            //出窗口
            while( hash[s[right]]>1)
            {
                hash[s[left]]--;
                left++;
            }
            //更新结果
            ret=max(ret,right-left+1);
        }
        return ret;
    }
};

3、最大连续一的个数

题目链接icon-default.png?t=O83Ahttps://leetcode.cn/problems/max-consecutive-ones-iii/description/

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

示例 1:

输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。

示例 2:

输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

解题代码:

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int len=nums.size();
        int ret=0;
        for(int left=0,right=0;right<len;right++)
        {
            //进窗口
            if(nums[right]==0) k--;
            //出窗口
            while(k<0)
            {
                if(nums[left]==0) k++;
                left++; 
            }
            //更新结果
            ret=max(ret,right-left+1);
        }
        return ret;
    }
};

4、将x见到0的最小操作数 

题目链接icon-default.png?t=O83Ahttps://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

解题代码:

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n=nums.size();
        int ret=0,len=0,sum1=0,sum2=0;
        //全部求元素之和
        for(auto e:nums) sum1+=e;
        if(sum1==x)
        return n;
        //求中间元素之和
        int target=sum1-x;
        for(int left=0,right=0;right<n;right++)
        {
            //进窗口
            sum2+=nums[right];
            //出窗口
            while(left<n&&sum2>target) sum2-=nums[left++];
            //更新结果
            if(sum2==target) len=max(len,right-left+1);
        }
        //转换最小结果
        return len==0?-1:n-len;
    }
};

5、完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

猜你喜欢

转载自blog.csdn.net/2301_80221228/article/details/143053495