【滑动窗口】LeetCode 1658题解 | 将 x 减到 0 的最小操作数

将 x 减到 0 的最小操作数

一、题目链接

将 x 减到 0 的最小操作数

二、题目

三、题目解析

以示例1为例:

四、算法原理

像"题目解析"中正面删除并修改数组元素的操作太困难,那就试试反面操作 ------ 正难则反思想。

正面操作:在一个数组中的左右边分别找一个小区间,左右区间中的数之和分别为a、b,使这两个小区间中的数之和为x,即 a + b = x。

反面操作:sum为数组中所有元素的和。中间是一段连续的区域,和为sum - x 。最小操作次数对应左右两个小区间中的数的个数最小,对等找中间一段连续区域中数的个数最多。

那么本题思路转化为:找出最长的子数组的长度(len),所有元素之和为sum-x(target)。(与【滑动窗口】系列的第一题类似)

为了更具有普遍性,把一个数组抽象成一段横线分析。在暴力解法的基础上找到最优解:

sum:标记双指针所指区域中的所有数之和。

right向后枚举的过程中,若right从当前位置所指是sum < target,恰好往后一步就有两种可能:sum == target或者sum > target,不管哪一种,right都不用向后枚举了,再往后肯定sum>target。规律1:right向后枚举的过程中,若找到一种结果或者sum>target,right不用向后枚举了。

这时再依次枚举left,left右移一步,按照暴力解法,此时right应回退枚举,但是经过分析right是不用回退的,这是为什么呢?蓝色区间中的数之和小于target,left右移一步,紫色区间中的数之和一定也小于target,所以right不用回退。规律2:left右移的过程中,right也右移 ------ 同向双指针。 这时新区间(右图紫色区间)中的和有两种情况:sum == target,更新结果;sum < target,right继续右移枚举找sum>=target。

步骤:

直到right到最后为止,最终结果是len,即最长长度,别忘了要n-len。

五、编写代码

细节问题:目标值target可能是小于0的数。题目中提示了数组中所有元素的和都是大于1的。数组中的元素只有大于等于1才能用滑动窗口,若有小于0的元素,随着right向后枚举,就没有了sum的数越来越大的单调性。所以,若target<0,是找不到对应元素的。

若target==0,则最小操作次数是0次。

cpp 复制代码
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        // 求target:sum-x
        int sum = 0;
        for (auto e : nums) sum += e;
        int target = sum - x;
        // 细节问题
        if (target < 0) return -1;
        // 滑动窗口
        int n = nums.size();
        int ret = -1;
        for (int left = 0, right = 0, tmp = 0; right < n; ++right)
        {
            tmp += nums[right];// 进窗口
            while (tmp > target)// 判断
                tmp -= nums[left++];// 出窗口
            if (tmp == target) ret = max(ret, right - left + 1);// 更新结果
        }
        // 返回最小操作数
        if (ret == -1) return ret;
        else return n - ret;
    }
};

六、时空复杂度

时间复杂度是O(n)

空间复杂度是O(1):只用了几个有限的变量。

相关推荐
运维-大白同学9 分钟前
go-数据库基本操作
开发语言·数据库·golang
动感光博20 分钟前
Unity(URP渲染管线)的后处理、动画制作、虚拟相机(Virtual Camera)
开发语言·人工智能·计算机视觉·unity·c#·游戏引擎
丶Darling.36 分钟前
Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先
数据结构·c++·算法·二叉树
蚰蜒螟1 小时前
深入解析JVM字节码解释器执行流程(OpenJDK 17源码实现)
开发语言·jvm·python
keke101 小时前
Java【14_2】接口(Comparable和Comparator)、内部类
java·开发语言
思茂信息1 小时前
CST软件对OPERA&CST软件联合仿真汽车无线充电站对人体的影响
c语言·开发语言·人工智能·matlab·汽车·软件构建
CN.LG1 小时前
Java 乘号来重复字符串的功能
java·开发语言
lqjun08271 小时前
Pytorch实现常用代码笔记
人工智能·pytorch·笔记
L_cl1 小时前
【Python 算法零基础 3.递推】
算法
川川菜鸟2 小时前
2025长三角数学建模C题完整思路
c语言·开发语言·数学建模