[路飞][LeetCode]1658_将 x 减到 0 的最小操作数

72 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

看一百遍美女,美女也不一定是你的。但你刷一百遍算法,知识就是你的了~~

谁能九层台,不用累土起!

题目地址

题目

给你一个整数数组 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 。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104
  • 1 <= x <= 109

解题思路

  • 我们用滑动窗口的思路来解决本题
  • 用数组全部元素的和减去窗口内元素的和如果正好等于x,则表明满足题意
  • 我们在维护这个窗口的长度最大的时候,那么移除的元素就越少,也就是对应的操作数最少

解题代码

var minOperations = function(nums, x) {
    const len = nums.length
    const total = nums.reduce((prev,cur)=>prev+cur)  // 所有元素的和

    if(total<x) return -1  //边界处理,如果总和都不达 x,直接结束
    let res = Infinity  // 记录操作次数
    let sum = 0 // 用于记录窗口内元素的和
    let left =0 
    let right = 0
    while(right<len){
        sum += nums[right]
        while(total-sum<x){ // 窗口外元素的和小于x  需要收紧窗口
            sum -= nums[left]
            left++
        }
        if(total-sum==x){ // 满足要求时,res取操作次数更少的
            res =Math.min(res,len-(right-left+1))
        }
        right++
    }
    return res ==Infinity?-1:res
};

生活不是选择是热爱 我去寻我的心之所向素履以往 山高路远看世界也找自己.

如有任何问题或建议,欢迎留言讨论!