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

160 阅读2分钟

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

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

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

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

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

具体题目链接: 题目链接

思路:

思路:滑动窗口思路

窗口扩展时寻找可行解,窗口收缩时优化可行解

当滑动窗口可以定长时,一直维护k个长度的滑动窗口即可

当滑动窗口需要不定长时,需要通过特定条件(比如滑动窗口的总和)来判断left和right指针 到底是移动哪个

分析:

将随机删除两端元素变成寻找连续子序列
你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值,言外之意(找到一个和为 sum - x 的最长连续子数组)
sum:nums总和
x:需要减去两端的值
window:滑动窗口
windowsum:滑动窗口的总和
right:滑动窗口右端点
left:滑动窗口左端点
count = sum - x;
if(windowsize>0)说明要收缩,left++;
<0;说明不存在,返回-1;
这题都是正数,如果有负数,参考560,使用前缀和+hash

代码:

var minOperations = function(nums, x) {
    let n = nums.length;
    let res = -1;//保存答案的最值

    //sum总和
    let sum = 0;
    for(let i=0;i<n;i++) {
        sum+=nums[i];
    }

    let count = sum - x;//分情况判断>0 =0 <0的情况
    if(count < 0)return -1;

    let windowsum = 0;
    let right =0;
    let left = 0;
    while(right < n) {
        windowsum += nums[right];
        
        //当滑动窗口里面总和 大于 count值的时候, 说明要减少滑动窗口
        while(windowsum > count) {
            windowsum -= nums[left];//值也要跟着动起来
            left++;
        }
        if(windowsum == count) { //相等时,说明找到了一组解,保存最大的题解
            res = Math.max(res, right-left+1);
        }
        right++;
    }
    if(res == -1)return -1;
    return n - res;
};

总结:

这是算法系列文章「滑动窗口」的相关题解

类型滑动窗口类型题目,解题方法窗口扩展时寻找可行解,窗口收缩时优化可行解