Skip to content

Commit 8ecec84

Browse files
authored
feat: update solutions to lc problems: No.0903~0910 (doocs#2432)
1 parent 8b89c79 commit 8ecec84

File tree

9 files changed

+58
-176
lines changed

9 files changed

+58
-176
lines changed

solution/0900-0999/0903.Valid Permutations for DI Sequence/README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@
7373

7474
时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 是字符串的长度。
7575

76-
我们可以用前缀和优化时间复杂度,使得时间复杂度降低到 $O(n^2)$。另外,我们也可以用滚动数组优化空间复杂度,使得空间复杂度降低到 $O(n)$。
77-
7876
<!-- tabs:start -->
7977

8078
```python
@@ -224,7 +222,7 @@ function numPermsDISequence(s: string): number {
224222

225223
<!-- tabs:end -->
226224

227-
### 方法二
225+
我们可以用前缀和优化时间复杂度,使得时间复杂度降低到 $O(n^2)$。
228226

229227
<!-- tabs:start -->
230228

@@ -372,7 +370,7 @@ function numPermsDISequence(s: string): number {
372370

373371
<!-- tabs:end -->
374372

375-
### 方法三
373+
另外,我们也可以用滚动数组优化空间复杂度,使得空间复杂度降低到 $O(n)$。
376374

377375
<!-- tabs:start -->
378376

solution/0900-0999/0903.Valid Permutations for DI Sequence/README_EN.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ The final answer is $\sum_{j=0}^n f[n][j]$.
6868

6969
The time complexity is $O(n^3)$, and the space complexity is $O(n^2)$. Here, $n$ is the length of the string.
7070

71-
We can optimize the time complexity to $O(n^2)$ using prefix sums. Additionally, we can optimize the space complexity to $O(n)$ using a rolling array.
72-
7371
<!-- tabs:start -->
7472

7573
```python
@@ -219,7 +217,7 @@ function numPermsDISequence(s: string): number {
219217

220218
<!-- tabs:end -->
221219

222-
### Solution 2
220+
We can optimize the time complexity to $O(n^2)$ using prefix sums.
223221

224222
<!-- tabs:start -->
225223

@@ -367,7 +365,7 @@ function numPermsDISequence(s: string): number {
367365

368366
<!-- tabs:end -->
369367

370-
### Solution 3
368+
Additionally, we can optimize the space complexity to $O(n)$ using a rolling array.
371369

372370
<!-- tabs:start -->
373371

solution/0900-0999/0904.Fruit Into Baskets/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ j i
9191
j i
9292
```
9393

94-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `fruits` 的长度。
94+
时间复杂度 $O(n)$,其中 $n$ 为数组 `fruits` 的长度。空间复杂度 $O(1)$
9595

9696
<!-- tabs:start -->
9797

@@ -231,7 +231,7 @@ impl Solution {
231231

232232
但本题实际上求的是水果的最大数目,也就是“最大”的窗口,我们没有必要缩小窗口,只需要让窗口单调增大。于是代码就少了每次更新答案的操作,只需要在遍历结束后将此时的窗口大小作为答案返回即可。
233233

234-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `fruits` 的长度。
234+
时间复杂度 $O(n)$,其中 $n$ 为数组 `fruits` 的长度。空间复杂度 $O(1)$
235235

236236
<!-- tabs:start -->
237237

solution/0900-0999/0907.Sum of Subarray Minimums/README.md

-57
Original file line numberDiff line numberDiff line change
@@ -300,61 +300,4 @@ impl Solution {
300300

301301
<!-- tabs:end -->
302302

303-
### 方法二
304-
305-
<!-- tabs:start -->
306-
307-
```rust
308-
const MOD: i64 = (1e9 as i64) + 7;
309-
310-
impl Solution {
311-
pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 {
312-
let n: usize = arr.len();
313-
let mut ret: i64 = 0;
314-
let mut left: Vec<i32> = vec![-1; n];
315-
let mut right: Vec<i32> = vec![n as i32; n];
316-
// Index stack, store the index of the value in the given array
317-
let mut stack: Vec<i32> = Vec::new();
318-
319-
// Find the first element that's less than the current value for the left side
320-
// The default value of which is -1
321-
for i in 0..n {
322-
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] {
323-
stack.pop();
324-
}
325-
if !stack.is_empty() {
326-
left[i] = *stack.last().unwrap();
327-
}
328-
stack.push(i as i32);
329-
}
330-
331-
stack.clear();
332-
333-
// Find the first element that's less or equal than the current value for the right side
334-
// The default value of which is n
335-
for i in (0..n).rev() {
336-
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] {
337-
stack.pop();
338-
}
339-
if !stack.is_empty() {
340-
right[i] = *stack.last().unwrap();
341-
}
342-
stack.push(i as i32);
343-
}
344-
345-
// Traverse the array, to find the sum
346-
for i in 0..n {
347-
ret +=
348-
((((right[i] - (i as i32)) * ((i as i32) - left[i])) as i64) * (arr[i] as i64)) %
349-
MOD;
350-
ret %= MOD;
351-
}
352-
353-
(ret % (MOD as i64)) as i32
354-
}
355-
}
356-
```
357-
358-
<!-- tabs:end -->
359-
360303
<!-- end -->

solution/0900-0999/0907.Sum of Subarray Minimums/README_EN.md

+31-58
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,37 @@ Sum is 17.
3737

3838
## Solutions
3939

40-
### Solution 1
40+
### Solution 1: Monotonic Stack
41+
42+
The problem asks for the sum of the minimum values of each subarray, which is equivalent to finding the number of subarrays for which each element $arr[i]$ is the minimum, then multiplying by $arr[i]$, and finally summing these up.
43+
44+
Therefore, the focus of the problem is to find the number of subarrays for which $arr[i]$ is the minimum. For $arr[i]$, we find the first position $left[i]$ to its left that is less than $arr[i]$, and the first position $right[i]$ to its right that is less than or equal to $arr[i]$. The number of subarrays for which $arr[i]$ is the minimum is $(i - left[i]) \times (right[i] - i)$.
45+
46+
Note, why do we find the first position $right[i]$ to the right that is less than or equal to $arr[i]$, rather than less than $arr[i]$? This is because if we find the first position $right[i]$ to the right that is less than $arr[i]$, it will lead to duplicate calculations.
47+
48+
Let's take an example to illustrate. For the following array:
49+
50+
The element at index $3$ is $2$, the first element to its left that is less than $2$ is at index $0$. If we find the first element to its right that is less than $2$, we get index $7$. That is, the subarray interval is $(0, 7)$. Note that this is an open interval.
51+
52+
```
53+
0 4 3 2 5 3 2 1
54+
* ^ *
55+
```
56+
57+
In the same way, we can find the subarray interval for the element at index $6$, and find that its subarray interval is also $(0, 7)$. That is, the subarray intervals for the elements at index $3$ and index $6$ are the same. This leads to duplicate calculations.
58+
59+
```
60+
0 4 3 2 5 3 2 1
61+
* ^ *
62+
```
63+
64+
If we find the first element to its right that is less than or equal to its value, there will be no duplication, because the subarray interval for the element at index $3$ becomes $(0, 6)$, and the subarray interval for the element at index $6$ is $(0, 7)$, which are not the same.
65+
66+
Back to this problem, we just need to traverse the array, for each element $arr[i]$, use a monotonic stack to find the first position $left[i]$ to its left that is less than $arr[i]$, and the first position $right[i]$ to its right that is less than or equal to $arr[i]$. The number of subarrays for which $arr[i]$ is the minimum is $(i - left[i]) \times (right[i] - i)$, then multiply by $arr[i]$, and finally sum these up.
67+
68+
Be aware of data overflow and modulo operations.
69+
70+
The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $arr$.
4171

4272
<!-- tabs:start -->
4373

@@ -264,61 +294,4 @@ impl Solution {
264294

265295
<!-- tabs:end -->
266296

267-
### Solution 2
268-
269-
<!-- tabs:start -->
270-
271-
```rust
272-
const MOD: i64 = (1e9 as i64) + 7;
273-
274-
impl Solution {
275-
pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 {
276-
let n: usize = arr.len();
277-
let mut ret: i64 = 0;
278-
let mut left: Vec<i32> = vec![-1; n];
279-
let mut right: Vec<i32> = vec![n as i32; n];
280-
// Index stack, store the index of the value in the given array
281-
let mut stack: Vec<i32> = Vec::new();
282-
283-
// Find the first element that's less than the current value for the left side
284-
// The default value of which is -1
285-
for i in 0..n {
286-
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] {
287-
stack.pop();
288-
}
289-
if !stack.is_empty() {
290-
left[i] = *stack.last().unwrap();
291-
}
292-
stack.push(i as i32);
293-
}
294-
295-
stack.clear();
296-
297-
// Find the first element that's less or equal than the current value for the right side
298-
// The default value of which is n
299-
for i in (0..n).rev() {
300-
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] {
301-
stack.pop();
302-
}
303-
if !stack.is_empty() {
304-
right[i] = *stack.last().unwrap();
305-
}
306-
stack.push(i as i32);
307-
}
308-
309-
// Traverse the array, to find the sum
310-
for i in 0..n {
311-
ret +=
312-
((((right[i] - (i as i32)) * ((i as i32) - left[i])) as i64) * (arr[i] as i64)) %
313-
MOD;
314-
ret %= MOD;
315-
}
316-
317-
(ret % (MOD as i64)) as i32
318-
}
319-
}
320-
```
321-
322-
<!-- tabs:end -->
323-
324297
<!-- end -->

solution/0900-0999/0907.Sum of Subarray Minimums/Solution2.rs

-48
This file was deleted.

solution/0900-0999/0908.Smallest Range I/README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,13 @@
5454

5555
## 解法
5656

57-
### 方法一
57+
### 方法一:数学
58+
59+
根据题目描述,我们可以将数组中的最大值加上 $k$,最小值减去 $k$,这样可以使得数组中的最大值和最小值之差变小。
60+
61+
因此,最终的答案就是 $\max(nums) - \min(nums) - 2 \times k$。
62+
63+
时间复杂度 $O(n)$,其中 $n$ 为数组 `nums` 的长度。空间复杂度 $O(1)$。
5864

5965
<!-- tabs:start -->
6066

solution/0900-0999/0908.Smallest Range I/README_EN.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@
5050

5151
## Solutions
5252

53-
### Solution 1
53+
### Solution 1: Mathematics
54+
55+
According to the problem description, we can add $k$ to the maximum value in the array and subtract $k$ from the minimum value. This can reduce the difference between the maximum and minimum values in the array.
56+
57+
Therefore, the final answer is $\max(nums) - \min(nums) - 2 \times k$.
58+
59+
The time complexity is $O(n)$, where $n$ is the length of the array `nums`. The space complexity is $O(1)$.
5460

5561
<!-- tabs:start -->
5662

solution/0900-0999/0910.Smallest Range II/README_EN.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@
5050

5151
## Solutions
5252

53-
### Solution 1
53+
### Solution 1: Greedy + Enumeration
54+
55+
According to the problem requirements, we need to find the minimum difference between the maximum and minimum values in the array. Each element can be increased or decreased by $k$, so we can divide the elements in the array into two parts, one part increased by $k$ and the other part decreased by $k$. Therefore, we should decrease the larger values in the array by $k$ and increase the smaller values by $k$ to ensure the minimum difference between the maximum and minimum values.
56+
57+
Therefore, we can first sort the array, then enumerate each element in the array, divide it into two parts, one part increased by $k$ and the other part decreased by $k$, and calculate the difference between the maximum and minimum values. Finally, take the minimum value among all differences.
58+
59+
The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$, where $n$ is the length of the array.
5460

5561
<!-- tabs:start -->
5662

0 commit comments

Comments
 (0)