616 字
3 分钟
1658. 将 x 减到 0 的最小操作数

1658. 将 x 减到 0 的最小操作数#

题目描述#

给你一个整数数组 nums 和一个整数 x。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。

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

核心思想#

正难则反 + 不定长滑动窗口。

从两端移除元素使和为 x,等价于在数组中间找一个最长子数组,其和为 total - x。

设 target = total - x:

  • 若 target < 0:无解,返回 -1
  • 若 target == 0:需移除全部元素,返回 n
  • 否则:用滑动窗口找和为 target 的最长子数组,答案 = n - 最长子数组长度

算法步骤#

  1. 计算 total = sum(nums), target = total - x
  2. 特判 target < 0 返回 -1,target == 0 返回 n
  3. 初始化 left = 0, window = 0, ans = -1
  4. 遍历 right 从 0 到 n-1:
    • window += nums[right]
    • 当 window > target 时:window -= nums[left], left += 1
    • 若 window == target:ans = max(ans, right - left + 1)
  5. 若 ans == -1 返回 -1,否则返回 n - ans

逐步举例#

以 nums = [1, 1, 4, 2, 3], x = 5 为例:

total = 11, target = 11 - 5 = 6

rightnums[right]window>6?收缩leftwindow==6?ans
011否—0否-1
112否—0否-1
246否—0是3
328是l=1, window=7; l=2, window=62是3
439是l=3, window=53否3

最终 ans = 3(子数组 [1,1,4]),返回 5 - 3 = 2。

验证:移除两端 [2, 3],和 = 5 ✓,操作数 = 2。

复杂度分析#

  • 时间复杂度:O(n)。每个元素最多进出窗口各一次。
  • 空间复杂度:O(1)。

参考#

代码实现#

from typing import List
class Solution:
def minOperations(self, nums: List[int], x: int) -> int:
total = sum(nums)
target = total - x
if target < 0:
return -1
if target == 0:
return len(nums)
n = len(nums)
ans = -1
left = window = 0
for right in range(n):
window += nums[right]
while window > target:
window -= nums[left]
left += 1
if window == target:
ans = max(ans, right - left + 1)
return -1 if ans == -1 else n - ans
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from solution import Solution
class TestMinOperations(unittest.TestCase):
def test_example1(self):
nums = [1, 1, 4, 2, 3]
x = 5
self.assertEqual(Solution().minOperations(nums, x), 2)
def test_example2(self):
nums = [5, 6, 7, 8, 9]
x = 4
self.assertEqual(Solution().minOperations(nums, x), -1)
def test_example3(self):
nums = [3, 2, 20, 1, 1, 3]
x = 10
self.assertEqual(Solution().minOperations(nums, x), 5)
def test_remove_all(self):
nums = [1, 2, 3]
x = 6
self.assertEqual(Solution().minOperations(nums, x), 3)
def test_remove_first(self):
nums = [5, 2, 3, 1, 1]
x = 5
self.assertEqual(Solution().minOperations(nums, x), 1)
def test_single_element(self):
nums = [1]
x = 1
self.assertEqual(Solution().minOperations(nums, x), 1)
def test_single_element_impossible(self):
nums = [1]
x = 2
self.assertEqual(Solution().minOperations(nums, x), -1)
if __name__ == "__main__":
unittest.main()
1658. 将 x 减到 0 的最小操作数
https://h1s97x.github.io/posts/coding/coding-1658-min-operations/
作者
H1S97X
发布于
2026-08-18
许可协议
CC BY-NC-SA 4.0
随机文章