Skip to content

Commit 070dbb6

Browse files
authored
feat: add solutions to lc problem: No.3356 (#4413)
No.3356.Zero Array Transformation II
1 parent 8ec2624 commit 070dbb6

File tree

3 files changed

+161
-2
lines changed

3 files changed

+161
-2
lines changed

solution/3300-3399/3356.Zero Array Transformation II/README.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,21 @@ tags:
109109

110110
<!-- solution:start -->
111111

112-
### 方法一
112+
### 方法一:差分数组 + 二分查找
113+
114+
我们注意到,查询的个数越多,越容易使得数组变成零数组,这存在单调性。因此,我们可以二分枚举查询的个数,判断在前 k 个查询下,是否可以将数组变成零数组。
115+
116+
我们定义二分查找的左边界 $l$ 和右边界 $r$,初始时 $l = 0$, $r = m + 1$,其中 $m$ 是查询的个数。我们定义一个函数 $\text{check}(k)$,表示在前 $k$ 个查询下,是否可以将数组变成零数组。我们可以使用差分数组来维护每个元素的值。
117+
118+
定义一个长度为 $n + 1$ 的数组 $d$,初始值全部为 $0$。对于前 $k$ 个查询的每个查询 $[l, r]$,我们将 $d[l]$ 加 $1$,将 $d[r + 1]$ 减 $1$。
119+
120+
然后我们遍历数组 $d$ 在 $[0, n - 1]$ 范围内的每个元素,累加前缀和 $s$,如果 $\textit{nums}[i] > s$,说明 $\textit{nums}$ 不能转换为零数组,返回 $\textit{false}$。
121+
122+
我们在二分查找的过程中,如果 $\text{check}(k)$ 返回 $\text{true}$,说明可以将数组变成零数组,我们就将右边界 $r$ 更新为 $k$,否则将左边界 $l$ 更新为 $k + 1$。
123+
124+
最后,我们判断 $l$ 是否大于 $m$,如果是,则返回 -1,否则返回 $l$。
125+
126+
时间复杂度 $O((n + m) \times \log m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别为数组 $\textit{nums}$ 和 $\textit{queries}$ 的长度。
113127

114128
<!-- tabs:start -->
115129

@@ -278,6 +292,50 @@ function minZeroArray(nums: number[], queries: number[][]): number {
278292
}
279293
```
280294

295+
#### Rust
296+
297+
```rust
298+
impl Solution {
299+
pub fn min_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> i32 {
300+
let n = nums.len();
301+
let m = queries.len();
302+
let mut d: Vec<i64> = vec![0; n + 1];
303+
let (mut l, mut r) = (0_usize, m + 1);
304+
305+
let check = |k: usize, d: &mut Vec<i64>| -> bool {
306+
d.fill(0);
307+
for i in 0..k {
308+
let (l, r, val) = (
309+
queries[i][0] as usize,
310+
queries[i][1] as usize,
311+
queries[i][2] as i64,
312+
);
313+
d[l] += val;
314+
d[r + 1] -= val;
315+
}
316+
let mut s: i64 = 0;
317+
for i in 0..n {
318+
s += d[i];
319+
if nums[i] as i64 > s {
320+
return false;
321+
}
322+
}
323+
true
324+
};
325+
326+
while l < r {
327+
let mid = (l + r) >> 1;
328+
if check(mid, &mut d) {
329+
r = mid;
330+
} else {
331+
l = mid + 1;
332+
}
333+
}
334+
if l > m { -1 } else { l as i32 }
335+
}
336+
}
337+
```
338+
281339
<!-- tabs:end -->
282340

283341
<!-- solution:end -->

solution/3300-3399/3356.Zero Array Transformation II/README_EN.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,21 @@ tags:
106106

107107
<!-- solution:start -->
108108

109-
### Solution 1
109+
### Solution 1: Difference Array + Binary Search
110+
111+
We notice that the more queries we use, the easier it is to turn the array into a zero array, which shows monotonicity. Therefore, we can use binary search to enumerate the number of queries and check whether the array can be turned into a zero array after the first $k$ queries.
112+
113+
We define the left boundary $l$ and right boundary $r$ for binary search, initially $l = 0$, $r = m + 1$, where $m$ is the number of queries. We define a function $\text{check}(k)$ to indicate whether the array can be turned into a zero array after the first $k$ queries. We can use a difference array to maintain the value of each element.
114+
115+
Define an array $d$ of length $n + 1$, initialized to all $0$. For each of the first $k$ queries $[l, r, val]$, we add $val$ to $d[l]$ and subtract $val$ from $d[r + 1]$.
116+
117+
Then we iterate through the array $d$ in the range $[0, n - 1]$, accumulating the prefix sum $s$. If $\textit{nums}[i] > s$, it means $\textit{nums}$ cannot be transformed into a zero array, so we return $\textit{false}$.
118+
119+
During the binary search, if $\text{check}(k)$ returns $\text{true}$, it means the array can be turned into a zero array, so we update the right boundary $r$ to $k$; otherwise, we update the left boundary $l$ to $k + 1$.
120+
121+
Finally, we check whether $l > m$. If so, return -1; otherwise, return $l$.
122+
123+
The time complexity is $O((n + m) \times \log m)$, and the space complexity is $O(n)$, where $n$ and $m$ are the lengths of the array $\textit{nums}$ and $\textit{queries}$, respectively.
110124

111125
<!-- tabs:start -->
112126

@@ -275,6 +289,50 @@ function minZeroArray(nums: number[], queries: number[][]): number {
275289
}
276290
```
277291

292+
#### Rust
293+
294+
```rust
295+
impl Solution {
296+
pub fn min_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> i32 {
297+
let n = nums.len();
298+
let m = queries.len();
299+
let mut d: Vec<i64> = vec![0; n + 1];
300+
let (mut l, mut r) = (0_usize, m + 1);
301+
302+
let check = |k: usize, d: &mut Vec<i64>| -> bool {
303+
d.fill(0);
304+
for i in 0..k {
305+
let (l, r, val) = (
306+
queries[i][0] as usize,
307+
queries[i][1] as usize,
308+
queries[i][2] as i64,
309+
);
310+
d[l] += val;
311+
d[r + 1] -= val;
312+
}
313+
let mut s: i64 = 0;
314+
for i in 0..n {
315+
s += d[i];
316+
if nums[i] as i64 > s {
317+
return false;
318+
}
319+
}
320+
true
321+
};
322+
323+
while l < r {
324+
let mid = (l + r) >> 1;
325+
if check(mid, &mut d) {
326+
r = mid;
327+
} else {
328+
l = mid + 1;
329+
}
330+
}
331+
if l > m { -1 } else { l as i32 }
332+
}
333+
}
334+
```
335+
278336
<!-- tabs:end -->
279337

280338
<!-- solution:end -->
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
impl Solution {
2+
pub fn min_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> i32 {
3+
let n = nums.len();
4+
let m = queries.len();
5+
let mut d: Vec<i64> = vec![0; n + 1];
6+
let (mut l, mut r) = (0_usize, m + 1);
7+
8+
let check = |k: usize, d: &mut Vec<i64>| -> bool {
9+
d.fill(0);
10+
for i in 0..k {
11+
let (l, r, val) = (
12+
queries[i][0] as usize,
13+
queries[i][1] as usize,
14+
queries[i][2] as i64,
15+
);
16+
d[l] += val;
17+
d[r + 1] -= val;
18+
}
19+
let mut s: i64 = 0;
20+
for i in 0..n {
21+
s += d[i];
22+
if nums[i] as i64 > s {
23+
return false;
24+
}
25+
}
26+
true
27+
};
28+
29+
while l < r {
30+
let mid = (l + r) >> 1;
31+
if check(mid, &mut d) {
32+
r = mid;
33+
} else {
34+
l = mid + 1;
35+
}
36+
}
37+
if l > m {
38+
-1
39+
} else {
40+
l as i32
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)