Skip to content

Commit 2a2ec4e

Browse files
committed
feat: add solutions to lc problem: No.1658
No.1658.Minimum Operations to Reduce X to Zero
1 parent 94e1a74 commit 2a2ec4e

File tree

9 files changed

+377
-155
lines changed

9 files changed

+377
-155
lines changed

solution/1600-1699/1658.Minimum Operations to Reduce X to Zero/README.md

+175-51
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,27 @@
4949

5050
<!-- 这里可写通用的实现逻辑 -->
5151

52-
前缀和 + 哈希表。
52+
**方法一:哈希表 + 前缀和**
5353

54-
题目可以转换为求中间连续子数组的最大长度,使得子数组的和为 `sum(nums) - x`
54+
我们可以将问题转换为求中间连续子数组的最大长度,使得子数组的和为 $x = sum(nums) - x$。
55+
56+
定义一个哈希表 `vis`,其中 `vis[s]` 表示前缀和为 $s$ 的最小下标。
57+
58+
遍历数组 `nums`,对于每个元素 $nums[i]$,我们先将 $nums[i]$ 加到前缀和 $s$ 上,如果哈希表中不存在 $s$,则将其加入哈希表,其值为当前下标 $i$。然后我们判断 $s - x$ 是否在哈希表中,如果存在,则说明存在一个下标 $j$,使得 $nums[j + 1,..i]$ 的和为 $x$,此时我们更新答案的最小值,即 $ans = min(ans, n - (i - j))$。
59+
60+
遍历结束,如果找不到满足条件的子数组,返回 $-1$,否则返回 $ans$。
61+
62+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 `nums` 的长度。
63+
64+
**方法二:双指针**
65+
66+
与方法一类似,我们要找到一个子数组,使得子数组的和为 $x = sum(nums) - x$。
67+
68+
定义两个指针 $j$ 和 $i$,初始时 $i = j = 0$,然后我们向右移动指针 $i$,将 $nums[i]$ 加到前缀和 $s$ 上。如果 $s \gt x$,那么我们循环向右移动指针 $j$,并且将 $nums[j]$ 从前缀和 $s$ 上减去,直到 $s \le x$。如果 $s = x$,我们可以更新答案的最小值,即 $ans = min(ans, n - (i - j + 1))$。继续向右移动指针 $i$,重复上述过程。
69+
70+
最后,如果找不到满足条件的子数组,返回 $-1$,否则返回 $ans$。
71+
72+
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `nums` 的长度。
5573

5674
<!-- tabs:start -->
5775

@@ -63,20 +81,36 @@
6381
class Solution:
6482
def minOperations(self, nums: List[int], x: int) -> int:
6583
x = sum(nums) - x
66-
n = len(nums)
67-
s = 0
68-
seen = {0: -1}
84+
vis = {0: -1}
6985
ans = inf
86+
s, n = 0, len(nums)
7087
for i, v in enumerate(nums):
7188
s += v
72-
if s not in seen:
73-
seen[s] = i
74-
if s - x in seen:
75-
j = seen[s - x]
89+
if s not in vis:
90+
vis[s] = i
91+
if s - x in vis:
92+
j = vis[s - x]
7693
ans = min(ans, n - (i - j))
7794
return -1 if ans == inf else ans
7895
```
7996

97+
```python
98+
class Solution:
99+
def minOperations(self, nums: List[int], x: int) -> int:
100+
x = sum(nums) - x
101+
ans = inf
102+
n = len(nums)
103+
s = j = 0
104+
for i, v in enumerate(nums):
105+
s += v
106+
while j <= i and s > x:
107+
s -= nums[j]
108+
j += 1
109+
if s == x:
110+
ans = min(ans, n - (i - j + 1))
111+
return -1 if ans == inf else ans
112+
```
113+
80114
### **Java**
81115

82116
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -88,20 +122,42 @@ class Solution {
88122
for (int v : nums) {
89123
x += v;
90124
}
91-
int s = 0;
125+
Map<Integer, Integer> vis = new HashMap<>();
126+
vis.put(0, -1);
92127
int n = nums.length;
93-
Map<Integer, Integer> seen = new HashMap<>();
94-
seen.put(0, -1);
95-
int ans = Integer.MAX_VALUE;
96-
for (int i = 0; i < n; ++i) {
128+
int ans = 1 << 30;
129+
for (int i = 0, s = 0; i < n; ++i) {
97130
s += nums[i];
98-
seen.putIfAbsent(s, i);
99-
if (seen.containsKey(s - x)) {
100-
int j = seen.get(s - x);
131+
vis.putIfAbsent(s, i);
132+
if (vis.containsKey(s - x)) {
133+
int j = vis.get(s - x);
101134
ans = Math.min(ans, n - (i - j));
102135
}
103136
}
104-
return ans == Integer.MAX_VALUE ? -1 : ans;
137+
return ans == 1 << 30 ? -1 : ans;
138+
}
139+
}
140+
```
141+
142+
```java
143+
class Solution {
144+
public int minOperations(int[] nums, int x) {
145+
x = -x;
146+
for (int v : nums) {
147+
x += v;
148+
}
149+
int n = nums.length;
150+
int ans = 1 << 30;
151+
for (int i = 0, j = 0, s = 0; i < n; ++i) {
152+
s += nums[i];
153+
while (j <= i && s > x) {
154+
s -= nums[j++];
155+
}
156+
if (s == x) {
157+
ans = Math.min(ans, n - (i - j + 1));
158+
}
159+
}
160+
return ans == 1 << 30 ? -1 : ans;
105161
}
106162
}
107163
```
@@ -112,21 +168,42 @@ class Solution {
112168
class Solution {
113169
public:
114170
int minOperations(vector<int>& nums, int x) {
115-
x = -x;
116-
for (int& v : nums) x += v;
117-
int s = 0, n = nums.size();
118-
unordered_map<int, int> seen;
119-
seen[0] = -1;
120-
int ans = INT_MAX;
121-
for (int i = 0; i < n; ++i) {
171+
x = accumulate(nums.begin(), nums.end(), 0) - x;
172+
unordered_map<int, int> vis{{0, -1}};
173+
int n = nums.size();
174+
int ans = 1 << 30;
175+
for (int i = 0, s = 0; i < n; ++i) {
122176
s += nums[i];
123-
if (!seen.count(s)) seen[s] = i;
124-
if (seen.count(s - x)) {
125-
int j = seen[s - x];
177+
if (!vis.count(s)) {
178+
vis[s] = i;
179+
}
180+
if (vis.count(s - x)) {
181+
int j = vis[s - x];
126182
ans = min(ans, n - (i - j));
127183
}
128184
}
129-
return ans == INT_MAX ? -1 : ans;
185+
return ans == 1 << 30 ? -1 : ans;
186+
}
187+
};
188+
```
189+
190+
```cpp
191+
class Solution {
192+
public:
193+
int minOperations(vector<int>& nums, int x) {
194+
x = accumulate(nums.begin(), nums.end(), 0) - x;
195+
int n = nums.size();
196+
int ans = 1 << 30;
197+
for (int i = 0, j = 0, s = 0; i < n; ++i) {
198+
s += nums[i];
199+
while (j <= i && s > x) {
200+
s -= nums[j++];
201+
}
202+
if (s == x) {
203+
ans = min(ans, n - (i - j + 1));
204+
}
205+
}
206+
return ans == 1 << 30 ? -1 : ans;
130207
}
131208
};
132209
```
@@ -139,19 +216,52 @@ func minOperations(nums []int, x int) int {
139216
for _, v := range nums {
140217
x += v
141218
}
219+
vis := map[int]int{0: -1}
220+
ans := 1 << 30
142221
s, n := 0, len(nums)
143-
seen := map[int]int{0: -1}
144-
ans := math.MaxInt32
145222
for i, v := range nums {
146223
s += v
147-
if _, ok := seen[s]; !ok {
148-
seen[s] = i
224+
if _, ok := vis[s]; !ok {
225+
vis[s] = i
149226
}
150-
if j, ok := seen[s-x]; ok {
227+
if j, ok := vis[s-x]; ok {
151228
ans = min(ans, n-(i-j))
152229
}
153230
}
154-
if ans == math.MaxInt32 {
231+
if ans == 1<<30 {
232+
return -1
233+
}
234+
return ans
235+
}
236+
237+
func min(a, b int) int {
238+
if a < b {
239+
return a
240+
}
241+
return b
242+
}
243+
```
244+
245+
```go
246+
func minOperations(nums []int, x int) int {
247+
x = -x
248+
for _, v := range nums {
249+
x += v
250+
}
251+
ans := 1 << 30
252+
s, n := 0, len(nums)
253+
j := 0
254+
for i, v := range nums {
255+
s += v
256+
for j <= i && s > x {
257+
s -= nums[j]
258+
j++
259+
}
260+
if s == x {
261+
ans = min(ans, n-(i-j+1))
262+
}
263+
}
264+
if ans == 1<<30 {
155265
return -1
156266
}
157267
return ans
@@ -169,26 +279,40 @@ func min(a, b int) int {
169279

170280
```ts
171281
function minOperations(nums: number[], x: number): number {
172-
const total = nums.reduce((a, c) => a + c, 0);
173-
if (total < x) return -1;
174-
// 前缀和 + 哈希表, 求何为total - x的最长子序列
282+
x = nums.reduce((a, b) => a + b, 0) - x;
283+
const vis = new Map();
284+
vis.set(0, -1);
285+
const n = nums.length;
286+
let ans = 1 << 30;
287+
for (let i = 0, s = 0; i < n; ++i) {
288+
s += nums[i];
289+
if (!vis.has(s)) {
290+
vis.set(s, i);
291+
}
292+
if (vis.has(s - x)) {
293+
const j = vis.get(s - x);
294+
ans = Math.min(ans, n - (i - j));
295+
}
296+
}
297+
return ans == 1 << 30 ? -1 : ans;
298+
}
299+
```
300+
301+
```ts
302+
function minOperations(nums: number[], x: number): number {
303+
x = nums.reduce((a, b) => a + b, 0) - x;
175304
const n = nums.length;
176-
const target = total - x;
177-
let hashMap = new Map();
178-
hashMap.set(0, -1);
179-
let pre = 0;
180-
let ans = -1;
181-
for (let right = 0; right < n; right++) {
182-
pre += nums[right];
183-
if (!hashMap.has(pre)) {
184-
hashMap.set(pre, right);
305+
let ans = 1 << 30;
306+
for (let i = 0, j = 0, s = 0; i < n; ++i) {
307+
s += nums[i];
308+
while (j <= i && s > x) {
309+
s -= nums[j++];
185310
}
186-
if (hashMap.has(pre - target)) {
187-
let left = hashMap.get(pre - target);
188-
ans = Math.max(right - left, ans);
311+
if (s == x) {
312+
ans = Math.min(ans, n - (i - j + 1));
189313
}
190314
}
191-
return ans == -1 ? -1 : n - ans;
315+
return ans == 1 << 30 ? -1 : ans;
192316
}
193317
```
194318

0 commit comments

Comments
 (0)