当前位置: 首页 > article >正文

滑动窗口——将x减到0的最小的操作数

一.题目描述

1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)

二.题目解析 

题目还是很简单的,我们只需要每次在数组的左边或者右边选一个数,让x减去它,然后重复这个过程,如果x恰好可以减到0,那么就返回最小的操作次数;如果不能,则返回-1.

需要注意的是:减去了的数就不能再减了。

下面结合示例一来说明:

我们即可以先删除前两个1,然后删除最左边的3,就可以答案目的,此时操作3次;

我们也可以删除最右边的3、2,此时只需要操作两次。

所以最小的操作数就是2.


但是如果这样就写代码的话会非常复杂,我们可以采取"正难则反"的原则来解题。

我们要找到几个数的和是x,且这几个数分布在数组的左右,题目的要求就是在数组左右找到一小块区间,让区间的和为x即可,而且这两个区间的长度要尽可能地小:a+b ==x

那么我们可以将问题转换一下,既然左右的和为x,那么中间的和就等于数组的和tol-x。此时我们的问题就转化为了求一段连续的子区间,要求该子区间的和为tol-x。当我们求出该子区间的长度之后,该题的结果就等于该数组的总长度减去该子区间的长度len。

三.算法原理

1.暴力解法

枚举出所有的子区间,找到其中和为tol-x,且最长的区间。

方法就是先固定一个左端点left,然后枚举右端点,同时求和。找出满足的区间即可。

暴力枚举的时间复杂度为:O(N^2),空间复杂度为O(1)。

2.滑动窗口

我们借助暴力解法来进行优化:

优化1:当子区间的和大于tol-x的时候,我们就不必继续让right继续++了,因为后面的区间已经不满足条件了,枚举了也是白枚举。我们此时让left++,获得一个新的子区间,判断是否满足要求。

如果满足要求了,left就不用动了。

优化2:当left找到一个新位置之后,right不必重新从left的位置开始,直接从原本的位置继续向右就行了。

为什么呢? 

因为当前[left,right]区间已经满足要求了即区间和<=tol-x,那么就算你重新从left开始走,依旧会走到那个地方,这是一定的。所以可以直接舍弃到回退的这一步。

综上,left和right两个指针都同时向右走,所以这道题可以用滑动窗口来解决。

滑动窗口步骤:

进窗口:让区间的和加上right当前的元素;

判断:如果区间的和大于target了,此时让最左边的值出窗口,然后继续判断

更新结果:当区间满足条件后,还要进行判断,只有区间和等于target 才需要更新结果。

时间复杂度:O(N),空间复杂度:O(1).

四.代码实现

这道题还是有很多细节需要处理:当我们的目标值即最长的子区间的和小于0时,说明该区间不存在,即x不可能减小到0,此时返回-1即可。

因为如果不满足题意要返回-1,所以我们可以直接让长度为-1.

int left = 0;
int right = 0;
int tol= 0;//数组的和
for (auto e : nums)
{
    tol+= e;
}
int target = tol- x;//目标值,寻找最长子区间和为target
if (target < 0)
{
    return -1;
}

int sum = 0;
int len = -1;//子区间长度
while (right < nums.size())
{
    sum += nums[right];
    while (sum > target)
    {
        sum -= nums[left++];
    }

    if (sum == target)
    {
        len = max(len, right - left + 1);
    }
    right++;
}
return len == -1 ? -1 : nums.size() - len;

http://www.kler.cn/a/464064.html

相关文章:

  • 硬件-射频-PCB-常见天线分类-ESP32实例
  • 使用java语言,自定义redistemplate
  • Vue3 子组件向父组件传递消息(Events)
  • overleaf写学术论文常用语法+注意事项+审阅修订
  • Px4 V2.4.8飞控Mavlink命令控制说明
  • 2024年度总结答疑
  • 长时间序列预测算法---Informer
  • Cocos游戏中集成RichTap高品质振动
  • SpringCloud微服务架构
  • selenium 确保页面完全加载
  • react 优化方案
  • vue设计与实现-权衡的艺术
  • 打造三甲医院人工智能矩阵新引擎(一):文本大模型篇--基于GPT-4o的探索
  • SpringBoot开发——常用的几种参数传递和参数接收方式
  • js 中的递归应用+异步递归
  • Ungoogled Chromium127编译指南 Linux篇 - 拉取仓库(七)
  • IP-Guard对SolidWorks PDM 加密授权说明
  • Linux 系统中 .d 目录有什么用?
  • 电视广播制式:N制与P制
  • Guava常见特性操作
  • node.js 浅析 与 了解
  • 【视觉SLAM:十一、设计SLAM系统】
  • 人大金仓数据库基于Linux系统的数据库软件安装指南
  • PlantUML 时序图 基本例子
  • 民宿酒店预订系统小程序+uniapp全开源+搭建教程
  • Vue演练场基础知识(三)