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 reducexto exactly0if it is possible, otherwise, return-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:
1
2
3
4
Input:
nums = [5,6,7,8,9], x = 4
Output:
-1
Example 3:
1
2
3
4
5
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.
The idea is to try every possible way of removing elements from either the left or right end of the array, subtracting their values from x at each step. We recursively explore both options at every step, keeping track of the minimum number of operations needed to reduce x to exactly zero. Memoization is used to avoid recalculating results for the same state.
funcminOperations(nums []int, xint) int {
typekeystruct{ l, r, remint }
memo:= make(map[key]int)
vardfsfunc(int, int, int) intdfs = func(l, r, remint) int {
ifrem==0 {
return0 }
ifrem < 0||l > r {
return-1 }
k:=key{l, r, rem}
ifv, ok:=memo[k]; ok {
returnv }
left:=dfs(l+1, r, rem-nums[l])
right:=dfs(l, r-1, rem-nums[r])
ans:=1<<31-1ifleft!=-1&&1+left < ans {
ans = 1+left }
ifright!=-1&&1+right < ans {
ans = 1+right }
ifans==1<<31-1 {
memo[k] = -1 } else {
memo[k] = ans }
returnmemo[k]
}
returndfs(0, len(nums)-1, x)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution {
publicintminOperations(int[] nums, int x) {
Map<String, Integer> memo =new HashMap<>();
return dfs(nums, 0, nums.length- 1, x, memo);
}
privateintdfs(int[] nums, int l, int r, int rem, Map<String, Integer> memo) {
if (rem == 0) return 0;
if (rem < 0 || l > r) return-1;
String key = l +","+ r +","+ rem;
if (memo.containsKey(key)) return memo.get(key);
int left = dfs(nums, l + 1, r, rem - nums[l], memo);
int right = dfs(nums, l, r - 1, rem - nums[r], memo);
int ans = Integer.MAX_VALUE;
if (left !=-1) ans = Math.min(ans, 1 + left);
if (right !=-1) ans = Math.min(ans, 1 + right);
memo.put(key, ans == Integer.MAX_VALUE?-1 : ans);
return memo.get(key);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution {
funminOperations(nums: IntArray, x: Int): Int {
val memo = mutableMapOf<Triple<Int, Int, Int>, Int>()
fundfs(l: Int, r: Int, rem: Int): Int {
if (rem ==0) return0if (rem < 0|| l > r) return -1val key = Triple(l, r, rem)
memo[key]?.let { returnit }
val left = dfs(l + 1, r, rem - nums[l])
val right = dfs(l, r - 1, rem - nums[r])
var ans = Int.MAX_VALUE
if (left != -1) ans = minOf(ans, 1 + left)
if (right != -1) ans = minOf(ans, 1 + right)
memo[key] = if (ans ==Int.MAX_VALUE) -1else ans
return memo[key]!! }
return dfs(0, nums.size - 1, x)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution:
defminOperations(self, nums: list[int], x: int) -> int:
from functools import lru_cache
n = len(nums)
@lru_cache(None)
defdfs(l: int, r: int, rem: int) -> int:
if rem ==0:
return0if rem <0or l > r:
return-1 left = dfs(l +1, r, rem - nums[l])
right = dfs(l, r -1, rem - nums[r])
ans = float('inf')
if left !=-1:
ans = min(ans, 1+ left)
if right !=-1:
ans = min(ans, 1+ right)
return-1if ans == float('inf') else ans
return dfs(0, n -1, x)
use std::collections::HashMap;
impl Solution {
pubfnmin_operations(nums: Vec<i32>, x: i32) -> i32 {
fndfs(nums: &Vec<i32>, l: usize, r: usize, rem: i32, memo: &mut HashMap<(usize, usize, i32), i32>) -> i32 {
if rem ==0 { return0; }
if rem <0|| l > r { return-1; }
iflet Some(&v) = memo.get(&(l, r, rem)) { return v; }
letmut ans =i32::MAX;
if l < nums.len() {
let left = dfs(nums, l +1, r, rem - nums[l], memo);
if left !=-1 { ans = ans.min(1+ left); }
}
if r < nums.len() {
let right = dfs(nums, l, r -1, rem - nums[r], memo);
if right !=-1 { ans = ans.min(1+ right); }
}
let res =if ans ==i32::MAX { -1 } else { ans };
memo.insert((l, r, rem), res);
res
}
let n = nums.len();
dfs(&nums, 0, n -1, x, &mut HashMap::new())
}
}
⏰ Time complexity: O(2^n) in the worst case, since at each step we can remove either the leftmost or rightmost element, leading to exponential possibilities. Memoization reduces repeated work, but the number of unique states is O(n^2 * x).
🧺 Space complexity: O(n^2 * x) due to the memoization table storing results for each combination of left, right, and remaining x.
Instead of removing elements from the ends, we can think in reverse: the elements we do not remove must form a contiguous subarray in the middle whose sum is totalSum - x. To minimize the number of operations, we want to maximize the length of this subarray. Thus, the problem reduces to finding the longest subarray with sum equal to totalSum - x.
classSolution {
public:int minOperations(vector<int>& nums, int x) {
int n = nums.size();
int target = accumulate(nums.begin(), nums.end(), 0) - x;
unordered_map<int, int> mp;
mp[0] =-1;
int ans =-1, sum =0;
for (int i =0; i < n; ++i) {
sum += nums[i];
mp[sum] = i;
if (mp.count(sum - target)) {
int len = i - mp[sum - target];
ans = max(ans, len);
}
}
return ans ==-1?-1: n - ans;
}
};
classSolution {
publicintminOperations(int[] nums, int x) {
int n = nums.length;
int target = 0;
for (int v : nums) target += v;
target -= x;
Map<Integer, Integer> map =new HashMap<>();
map.put(0, -1);
int ans =-1, sum = 0;
for (int i = 0; i < n; i++) {
sum += nums[i];
map.put(sum, i);
if (map.containsKey(sum - target)) {
int len = i - map.get(sum - target);
ans = Math.max(ans, len);
}
}
return ans ==-1 ?-1 : n - ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution {
funminOperations(nums: IntArray, x: Int): Int {
val n = nums.size
val target = nums.sum() - x
val map = mutableMapOf(0 to -1)
var ans = -1var sum = 0for (i in nums.indices) {
sum += nums[i]
map[sum] = i
map[sum - target]?.let { idx ->val len = i - idx
if (len > ans) ans = len
}
}
returnif (ans == -1) -1else n - ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
classSolution:
defminOperations(self, nums: list[int], x: int) -> int:
n = len(nums)
target = sum(nums) - x
mp = {0: -1}
ans =-1 s =0for i, v in enumerate(nums):
s += v
mp[s] = i
if (s - target) in mp:
l = i - mp[s - target]
if l > ans:
ans = l
return-1if ans ==-1else n - ans
use std::collections::HashMap;
impl Solution {
pubfnmin_operations(nums: Vec<i32>, x: i32) -> i32 {
let n = nums.len();
let target = nums.iter().sum::<i32>() - x;
letmut mp = HashMap::new();
mp.insert(0, -1);
letmut ans =-1;
letmut sum =0;
for (i, &v) in nums.iter().enumerate() {
sum += v;
mp.insert(sum, i asi32);
iflet Some(&idx) = mp.get(&(sum - target)) {
let len = i asi32- idx;
if len > ans { ans = len; }
}
}
if ans ==-1 { -1 } else { n asi32- ans }
}
}