将 x 减到 0 的最小操作数【LC1658】
You are given an integer array
nums
and an integerx
. In one operation, you can either remove the leftmost or the rightmost element from the arraynums
and subtract its value fromx
. Note that this modifies the array for future operations.Return the minimum number of operations to reduce
x
to exactly0
if it is possible*, otherwise, return*-1
.
跟周赛3252516. 每种字符至少取 K 个很像,所以很快就过啦 nice (在家过着每天是礼拜几都不知道的日子 还以为自己错过了周赛)
-
思路:题意可以转化为数组前缀和+后缀和
sum
为 x x x的最小长度- 假设左侧取到
n
u
m
s
[
i
]
nums[i]
nums[i],右侧取到
n
u
m
s
[
j
]
nums[j]
nums[j],由于和一定,因此随着
i
i
i的增大,
j
j
j也会增大,因此可以先记录符合条件的
i
i
i的最小位置,然后从大到小枚举
j
j
j,并使
i
i
i尽可能左移,当
sum==x
时,更新最小长度。
- 假设左侧取到
n
u
m
s
[
i
]
nums[i]
nums[i],右侧取到
n
u
m
s
[
j
]
nums[j]
nums[j],由于和一定,因此随着
i
i
i的增大,
j
j
j也会增大,因此可以先记录符合条件的
i
i
i的最小位置,然后从大到小枚举
j
j
j,并使
i
i
i尽可能左移,当
-
实现
class Solution { public int minOperations(int[] nums, int x) { int n = nums.length, res = Integer.MAX_VALUE; int sum = 0, l = -1; // 记录前缀和大于等于sum的最小左边界 while (l + 1 < n && sum < x){ sum += nums[++l]; } // 如果最大前缀和小于x,那么不可能将x减小至0,返回-1 if (sum < x){ return -1; }else if (sum == x){ res = l + 1; } for (int r = n - 1; r > l; r--){ sum += nums[r]; // 收缩左边界 while (sum > x && l >= 0){ sum -= nums[l--]; } if (sum == x) res = Math.min(res, l + 1 + n - r); } return res == Integer.MAX_VALUE ? - 1: res; } }
- 复杂度
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
- 复杂度