1658 - Minimum Operations to Reduce X to Zero
Difficulty: Medium | Pattern: Sliding Window (Complementary) | Company tags: Amazon, Google, Uber
Problem Statement
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, or -1 if it's not possible.
Example 1:
Input: nums = [1,1,4,2,3], x = 5
Output: 2
Explanation: Remove 4 from right, 1 from right: 4+1=5 (wait, but 4+1=5 ✓). Or remove last two: 2+3=5 ✓.
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
Algorithm Flow
Approach: Sliding Window on Middle (Complementary) — O(n)
Key insight: Instead of finding the shortest prefix+suffix summing to x, find the longest subarray in the middle summing to total - x. The answer is n - len(longest middle subarray).
def minOperations(nums: list[int], x: int) -> int:
target = sum(nums) - x
if target < 0:
return -1
if target == 0:
return len(nums)
left = 0
current_sum = 0
max_len = -1
for right in range(len(nums)):
current_sum += nums[right]
while current_sum > target and left <= right:
current_sum -= nums[left]
left += 1
if current_sum == target:
max_len = max(max_len, right - left + 1)
return len(nums) - max_len if max_len != -1 else -1
Dry Run
nums = [1,1,4,2,3], x=5, total=11, target=11-5=6
| right | nums[right] | window | sum | equals 6? |
|---|---|---|---|---|
| 0 | 1 | [0,0] | 1 | No |
| 1 | 1 | [0,1] | 2 | No |
| 2 | 4 | [0,2] | 6 | Yes, len=3 |
| 3 | 2 | [0,3] | 8 | shrink: [1,3]=7, [2,3]=6, len=2 |
| 4 | 3 | [2,4] | 9 | shrink: [3,4]=5, no |
max_len = 3, answer = 5 - 3 = 2 ✓
Edge Cases
sum(nums) < x→ impossible → -1sum(nums) == x→ take all elements → return ntarget = 0→ empty middle → take all
Complexity
- Time: O(n) — sliding window, each element added/removed once
- Space: O(1)
Key Terms
| Term | Definition |
|---|---|
| Complementary transformation | Reframing "shortest prefix+suffix" as "longest middle subarray" — a common trick for two-ended removal problems. |
| Sliding window | A two-pointer technique that expands/shrinks a contiguous range while maintaining a running sum or condition. |
| Target sum | Here, sum(nums) - x — the sum the middle subarray must hit so the remaining prefix+suffix sums to exactly x. |
| Monotonic shrink | The window's left pointer only moves forward, never backward, keeping the algorithm linear overall. |
FAQ
Q: Why transform the problem into finding the longest middle subarray?
A: Directly tracking a prefix and suffix that sum to x requires checking many combinations; reframing it as "keep the largest middle chunk you can afford to leave untouched" reduces the problem to a single sliding window over one target sum.
Q: Does the sliding window work here because all numbers are positive?
A: Yes — the constraint nums[i] >= 1 guarantees that as the window grows, the sum only increases, and shrinking from the left only decreases it, which is what makes the two-pointer shrink-on-overflow logic correct.
Q: What if nums contained negative numbers?
A: The sliding window would break, since growing the window wouldn't monotonically increase the sum. You'd need a different approach, such as prefix sums with a hash map.
Q: What does it mean if target == 0?
A: It means sum(nums) == x, so removing the entire array (using every element as prefix/suffix) satisfies the condition, and the answer is len(nums).
Q: How would you extend this to removing from three or more ends, or a circular array? A: For a circular array, you'd double the array or handle wraparound explicitly; for more removal points, the middle-subarray trick no longer applies directly and a different DP/greedy formulation would be needed.
Quick Revision
- Pattern: sliding window on the complement of the original ask.
- Convert "remove prefix+suffix summing to x" into "keep longest middle subarray summing to
total - x". - If target < 0, it's impossible → return -1.
- Expand the window with
right; while sum exceeds target, shrink fromleft. - Whenever sum equals target, update
max_lenwith the current window size. - Final answer:
n - max_len, or -1 if no valid window was ever found. - Works only because all
nums[i] >= 1(strictly positive), enabling monotonic window growth/shrink. - Time complexity: O(n) single pass; space O(1).
Related Problems
- 3 - Longest Substring Without Repeating Characters — same expand/shrink sliding-window skeleton.
- 42 - Trapping Rain Water — another two-pointer technique reasoning about complementary regions of an array.
- Pattern match: "maximum subarray sum with a fixed target" problems (e.g., max consecutive ones with k flips) use the identical shrink-when-invalid sliding window.