leecode1658 将x减小到0的最小操作数

总结

我觉得这个题目会的人会觉得很简单,不会的人会觉得很难,关键在于有没有想到反向思维,当正面思考考虑的情况有很多的时候我们需要进行反向思考

我最开始就是正向思考的,没有做出来这个题。

正向思考

  1. 定义左右指针进行遍历的时候,当此时的x不满足情况后如何修改这个指针

    1. 这一步也就是回退,我们需要考虑如何将这个指针进行回退
      比如说当执行了x-=nums[right]后,发现x<0了,我们要回退,x+=nums[right],然后让x-=nums[left]。
    2. 回退的过程有一个点很难处理,就是我们如何判断回退的是左边还是右边。
    3. 还有一个问题就是回退的时候边界很难处理,容易越界

后来本来想看题解了,觉得自己做不出来了,我突然发现leecode竟然还有提示

提示是,反向思考以下,与其用前缀和后缀,可以考虑去找这个最大子数组

然后就想明白了

反向思维思路

  1. 先对数组求和,然后数组和-x得到了一个数y
  2. 此时我们就需要找这个数组中内部最长的数组=y的情况,就将这个题转换为了一个滑动窗口找最长子数组的问题。
  3. 之后就简单了

代码如下

java 复制代码
public int minOperations(int[] nums, int x) {
    int len = nums.length;
    int left = 0,min=100001,sum=0;
    for(int a:nums){
        sum+=a;
    }
    int y= sum-x;//找出其中和为y的最大子数组,其余的就是这个x和y了
    if(y<0){
        return -1;
    }
    sum = 0;
    for(int right = 0;right<len;right++){
        sum+=nums[right];
        while(sum>y){
            sum-=nums[left];
            left++;
        }
        if(sum==y){
            min= Math.min(min,len-(right-left+1));
        }
    }
    return min==100001?-1:min;
}

灵神的思路

思路1,反向思维,滑动窗口

灵神的思路和我的类似,唯一区别在于它是直接算的数组的最大长度,然后得出的最小结果,我是直接算的最小的结果

思路2,直接双指针

这个思路有点奇特,他是先找出了最长后缀,对right指针进行了移动,然后不断遍历left指针,当left指针不满足条件的时候,只去修改右侧指针即可,相比我的想法,不满足条件之后对左右指针进行判断进行修改,这个地方只对这个right进行了修改

java 复制代码
class Solution {
    public int minOperations(int[] nums, int x) {
        int n = nums.length;
        int sum = 0;
        int right = n;
        while (right > 0 && sum + nums[right - 1] <= x) { // 计算最长后缀
            right--;
            sum += nums[right];
        }
        if (right == 0 && sum < x) {
            return -1; // 全部移除也无法满足要求
        }

        int ans = sum == x ? n - right : n + 1;
        for (int left = 0; left < n; left++) {
            sum += nums[left];
            while (right < n && sum > x) {
                sum -= nums[right];
                right++; // 缩小后缀长度
            }
            if (sum > x) {
                break; // 缩小失败,说明前缀过长
            }
            if (sum == x) {
                ans = Math.min(ans, left + 1 + n - right); // 前缀+后缀长度
            }
        }
        return ans > n ? -1 : ans;
    }
}

作者:灵茶山艾府
链接:https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/solutions/2048811/ni-xiang-si-wei-pythonjavacgo-by-endless-b4jt/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关推荐
TranquilGlow3 天前
leecode1004 最大连续1的个数III
leecode题解