[LeetCode] 1658. Minimum Operations to Reduce X to Zero

You are given an integer array nums and an integer x. In one operation, you can either remove the leftmost or the rightmost element from the array nums and subtract its value from x. Note that this modifies the array for future operations.

Return the minimum number of operations to reduce x to exactly 0 if it's possible, otherwise, return -1.

Example 1:

Input: nums = [1,1,4,2,3], x = 5
Output: 2
Explanation: The optimal solution is to remove the last two elements to reduce x to zero.

Example 2:

Input: nums = [5,6,7,8,9], x = 4
Output: -1

Example 3:

Input: nums = [3,2,20,1,1,3], x = 10
Output: 5
Explanation: The optimal solution is to remove the last three elements and the first two elements (5 operations in total) to reduce x to zero.

Constraints:

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

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-operations-to-reduce-x-to-zero
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是前缀和/滑动窗口,我参考了这个帖子。首先我们对目标值 X 翻译一下,因为题目问的其实是数组中间的某个子数组,满足其数组和 = 数组全部数字的和 - 两边某一些数字,所以目标值 X = 数组所有元素的和 totalSum - 左边一些元素的和 left - 右边一些元素的和 right。参见如下这个截图。

 

所以这道题可以转化为寻找一个数组和为 totalSum - x 的子数组,并且试图让这个子数组的长度尽可能最长,从而我们就得出最少需要移除几个元素了。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public int minOperations(int[] nums, int x) {
 3         int target = 0;
 4         int len = nums.length;
 5         for (int num : nums) {
 6             target += num;
 7         }
 8         // corner case
 9         // 如果整个数组的和 == X,说明需要移除所有元素
10         if (target == x) {
11             return len;
12         }
13 
14         // normal case
15         // target = totalSum - x
16         target -= x;
17         HashMap<Integer, Integer> map = new HashMap<>();
18         map.put(0, -1);
19         int res = Integer.MIN_VALUE;
20         // 前缀和
21         int sum = 0;
22         for (int i = 0; i < len; i++) {
23             sum += nums[i];
24             // 找有没有前缀和 - 蓝色部分
25             if (map.containsKey(sum - target)) {
26                 res = Math.max(res, i - map.get(sum - target));
27             }
28             map.put(sum, i);
29         }
30         return res == Integer.MIN_VALUE ? -1 : len - res;
31     }
32 }

 

LeetCode 题目总结 

posted @ 2021-01-16 01:41  CNoodle  阅读(542)  评论(0编辑  收藏  举报