【刷题】 滑动窗口进阶

本文介绍了滑动窗口算法在LeetCode中的应用,包括将x减到0的最小操作数、水果成篮和找到字符串中所有字母异位词的解题思路。通过暴力枚举和哈希算法的优化,展示了滑动窗口在实际问题中的高效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
送给大家一句话:

在最黑暗的那段人生,是我自己把自己拉出深渊。没有那个人,我就做那个人。——中岛美嘉

前言

继续学习滑动窗口问题。
入门篇我们了解滑动窗口的原理和算法思路:

  1. 双指针如果同方向移动即可使用滑动窗口
  2. 滑动窗口的原理是数组的单调性
  3. 基本步骤:进窗口-判断-出窗口-更新结果

接下来我们继续巩固我们的算法思维。来看三道题目:

Leetcode 1658. 将 x 减到 0 的最小操作数

上连接 !!!1658. 将 x 减到 0 的最小操作数

题目描述

在这里插入图片描述
根据描述,就是从左右两边分别取数,直到x减到零。来看一个样例:

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

算法思路

来看最最最直接的算法:暴力枚举!!!因为只能取两头的元素,所以等价于中间留下的值的和恰好等于数组和减去x。那这样遍历所有的子串,找到最小的即可!!!
怎么进行优化呢?当然是使用单调性来进行优化:
每次我们统计一个子串的和时,想一想right有必要回到 left++ 然后从新开始遍历吗?
当然不用!!!
因为left 到 right 就不满足要求(中间留下的值的和大于数组和减去x),left++后right从left开始最终也会回到原来位置,所以没有必要。
那这样就形成了滑动窗口:

class Solution {
   
public:
    int minOperations(vector<int>& nums, int x) {
   
        //进窗口
        //判断
        //出窗口

        //求和
        int sum = 0;
        for(auto s:nums) sum += s;
		
        int tmp = 0;//中间量
        int ans = INT_MAX;
        //特殊情况处理
        if(sum - x == 0) return nums.size();
        if(sum - x < 0) return -1;
        int n = nums.size();
        for(int left = 0,right = 0;right < n;right++)
        {
   
        //进窗口
            tmp += nums[right];
            //判断
            while(sum - x < tmp && left < right)
            {
   
            	//出窗口
                tmp -= nums[left];
                //
                left++;
            }
            //更新结果
            if(sum - x == tmp) ans = min(ans,n - (right - left +1));

        }
        return ans == INT_MAX ? -1 : ans;
    }
};

这样完美解决!!!
过啦!!!

Leetcode 904. 水果成篮

家人们 !跟上我们的节奏!!! 904. 水果成篮

题目描述

在这里插入图片描述
这道题很有意思奥(奇怪的农场主人…)
根据题目描述,我们需要找到一个子串中(只能有两种水果)的最大长度!来看一个样例:

  • 输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
  • 输出:5
  • 解释:可以采摘 [1,2,1,1,2] 这五棵树。只有两种水果并且最长!

算法思路

直接来最暴力的算法:暴力枚举。遍历所有的子串找到符合条件的最长字串即可(当然肯定会超时!!!)
那么怎么进行优化呢???(当然是滑动窗口)
每次找到不符合条件的子串,有没有必要将right指向left呢???
当然没有!!! 最长的已经遍历过,从头开始完全没有必要!!!
1,2,1,1,2,3 不和条件 就没有必要重新遍历2,1,1,2,3

这里的判断方法借助哈希算法来解决:

class Solution {
   
public:
    int totalFruit(vector<int>& f) {
   
        //进窗口
        //判断
        //出窗口
        //更新答案
		//用来统计水果种数
        int hash[100001] = {
   0} , ret = 0;
        int n = f.size();
        //滑动窗口
        for(int left = 0,right = 0,kinds = 0 ; right < n;right++){
   
            //进窗口
            //如果哈希表中是0 那说明是新品种
            if(hash[f[right]] == 0) kinds++;
            hash[f[right]]++;
            //判断
            while(kinds > 2){
   
                hash[f[left]]--;
                //出窗口前要检查种类是否变化
                if(hash[f[left]] == 0) kinds--;
                left++;
            }
            //更新结果
            ret = max(ret,right - left + 1);
        }
        return ret;
    }
};

提交看一下:过啦!!!!!!!!!

Leetcode 438. 找到字符串中所有字母异位词

家人们!上车!!!438. 找到字符串中所有字母异位词

题目描述

在这里插入图片描述
这道题很有说法࿰

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我龙翔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值