LeetCode之将 x 减到 0 的最小操作数 -- 滑动窗口

https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/

题目描述

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

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

示例 1:

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

这道题的意思是在数组的左右两边取元素,看取出的元素之后是否等于x,左右两边具体取几个数都不知道,这就导致非常难了。

我们可以换一种思路,题目是要取的是数组的两端,那么剩下的就是数组的中间连续部分,我们可以找中间部分的最大长度,进而求出数组两边的长度之和

我们假设数组的总和是sum,那么中间的数组之和大于等于sum-x时,可以看做是一种情况

 

也就是转换成了求子数组之和大于 sum-x 的最长子数组

1.定义left,right 初始都为0,sum为整个数组之和,target为子数组要大于的数 sum-x

 

2.当right小于数组长度时,right向右移动,直到 left 到 right 的子数组之和大于 target 时停止,然后子数组之和 tmp 减去 nums[left] ,left 向右移动,然后看 tmp 是否等于 target,如果等于,则将len更新,直到 tmp < target ,最后 right 向右移动,重复第一步;

如果left移动时,tmp正好等于target,更新当前的 len = right -left

 

3.直到 right == 数组的长度,最后返回数组的长度 - len

代码
public int minOperations(int[] nums, int x) {
    int n = nums.length;
    int left = 0,right = 0;
    int sum = 0;
    for(int a:nums){ //求和
        sum +=a;
    }
    int target = sum-x;
    if (target<0){ //当整个数组之和小于x时,直接返回
        return -1;
    }
    int tmp = 0;
    int len = -1;
​
    while (right<n){
        tmp+=nums[right];
        right++;
        while (tmp>target){
            tmp-=nums[left];
            left++;
        }
        if (tmp==target){
            len = Math.max(len,right-left);
        }
    }
    if (len == -1){//当没有满足的子数组时
        return -1;
    }
    return nums.length-len;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值