题目:
给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。
如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。
解题思路:
- 建立一个两倍长的数组temp,以例一为例,temp = [1, 1, 4, 2, 3, 1, 1, 4, 2, 3],从中间开始尝试先长度为1在长度为2,不停尝试是否有和值为x的,并记录最小的个数,当然这几个数一定包括3或1,即最中间的两个数。且最大长度不大于nums长度。
- 题解的答案是滑动窗口,初始化时left=-1,right=0,即先假设全部算在里面,若是大了则right往后加,总值一直减小,当小于x时,停止left往后走,总值加上去nums[left],若最后left==right==n结束遍历,中间若是找到总值等于x,记录操作数,最后比较一下,若是操作数大于了长度则返回-1,否则返回操作数即可。
代码:
class Solution:
def minOperations(self, nums: List[int], x: int) -> int:
n = len(nums)
total = sum(nums)
# 如果总值都小于x,则不可能直接返回-1
if total < x:
return -1
# 初始化值
right = 0
lsum, rsum = 0, total
ans = n + 1
# left不断往右走,到n结束循环
for left in range(-1, n - 1):
# 当left向右走的过程中,将lsum加上去
if left != -1:
lsum += nums[left]
# 如果总值一直大于x则表示要减去数字,不断将right向右移动,并跟新rsum
# 如果=x及找到一组答案,或者right=n了,则退出while循环
while right < n and lsum + rsum > x:
rsum -= nums[right]
right += 1
# 有答案更新
if lsum + rsum == x:
ans = min(ans, (left + 1) + (n - right))
# 在遍历过程中若没有一组满足,则ans==n+1,返回-1.否则返回最小操作数
return -1 if ans > n else ans