diff --git a/solution/0900-0999/0903.Valid Permutations for DI Sequence/README.md b/solution/0900-0999/0903.Valid Permutations for DI Sequence/README.md index 58a5c26290625..5c41340e2c270 100644 --- a/solution/0900-0999/0903.Valid Permutations for DI Sequence/README.md +++ b/solution/0900-0999/0903.Valid Permutations for DI Sequence/README.md @@ -73,8 +73,6 @@ 时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 是字符串的长度。 -我们可以用前缀和优化时间复杂度,使得时间复杂度降低到 $O(n^2)$。另外,我们也可以用滚动数组优化空间复杂度,使得空间复杂度降低到 $O(n)$。 - ```python @@ -224,7 +222,7 @@ function numPermsDISequence(s: string): number { -### 方法二 +我们可以用前缀和优化时间复杂度,使得时间复杂度降低到 $O(n^2)$。 @@ -372,7 +370,7 @@ function numPermsDISequence(s: string): number { -### 方法三 +另外,我们也可以用滚动数组优化空间复杂度,使得空间复杂度降低到 $O(n)$。 diff --git a/solution/0900-0999/0903.Valid Permutations for DI Sequence/README_EN.md b/solution/0900-0999/0903.Valid Permutations for DI Sequence/README_EN.md index bd8007f696b2e..4c4c11fb645ba 100644 --- a/solution/0900-0999/0903.Valid Permutations for DI Sequence/README_EN.md +++ b/solution/0900-0999/0903.Valid Permutations for DI Sequence/README_EN.md @@ -68,8 +68,6 @@ The final answer is $\sum_{j=0}^n f[n][j]$. The time complexity is $O(n^3)$, and the space complexity is $O(n^2)$. Here, $n$ is the length of the string. -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. - ```python @@ -219,7 +217,7 @@ function numPermsDISequence(s: string): number { -### Solution 2 +We can optimize the time complexity to $O(n^2)$ using prefix sums. @@ -367,7 +365,7 @@ function numPermsDISequence(s: string): number { -### Solution 3 +Additionally, we can optimize the space complexity to $O(n)$ using a rolling array. diff --git a/solution/0900-0999/0904.Fruit Into Baskets/README.md b/solution/0900-0999/0904.Fruit Into Baskets/README.md index 807504e1191b1..f5a5481f09eaf 100644 --- a/solution/0900-0999/0904.Fruit Into Baskets/README.md +++ b/solution/0900-0999/0904.Fruit Into Baskets/README.md @@ -91,7 +91,7 @@ j i j i ``` -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `fruits` 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为数组 `fruits` 的长度。空间复杂度 $O(1)$。 @@ -231,7 +231,7 @@ impl Solution { 但本题实际上求的是水果的最大数目,也就是“最大”的窗口,我们没有必要缩小窗口,只需要让窗口单调增大。于是代码就少了每次更新答案的操作,只需要在遍历结束后将此时的窗口大小作为答案返回即可。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `fruits` 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为数组 `fruits` 的长度。空间复杂度 $O(1)$。 diff --git a/solution/0900-0999/0907.Sum of Subarray Minimums/README.md b/solution/0900-0999/0907.Sum of Subarray Minimums/README.md index 8b3977bcec63b..7d2f039ada97b 100644 --- a/solution/0900-0999/0907.Sum of Subarray Minimums/README.md +++ b/solution/0900-0999/0907.Sum of Subarray Minimums/README.md @@ -300,61 +300,4 @@ impl Solution { -### 方法二 - - - -```rust -const MOD: i64 = (1e9 as i64) + 7; - -impl Solution { - pub fn sum_subarray_mins(arr: Vec) -> i32 { - let n: usize = arr.len(); - let mut ret: i64 = 0; - let mut left: Vec = vec![-1; n]; - let mut right: Vec = vec![n as i32; n]; - // Index stack, store the index of the value in the given array - let mut stack: Vec = Vec::new(); - - // Find the first element that's less than the current value for the left side - // The default value of which is -1 - for i in 0..n { - while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] { - stack.pop(); - } - if !stack.is_empty() { - left[i] = *stack.last().unwrap(); - } - stack.push(i as i32); - } - - stack.clear(); - - // Find the first element that's less or equal than the current value for the right side - // The default value of which is n - for i in (0..n).rev() { - while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] { - stack.pop(); - } - if !stack.is_empty() { - right[i] = *stack.last().unwrap(); - } - stack.push(i as i32); - } - - // Traverse the array, to find the sum - for i in 0..n { - ret += - ((((right[i] - (i as i32)) * ((i as i32) - left[i])) as i64) * (arr[i] as i64)) % - MOD; - ret %= MOD; - } - - (ret % (MOD as i64)) as i32 - } -} -``` - - - diff --git a/solution/0900-0999/0907.Sum of Subarray Minimums/README_EN.md b/solution/0900-0999/0907.Sum of Subarray Minimums/README_EN.md index 472cf68d2eab5..a2ecff0290495 100644 --- a/solution/0900-0999/0907.Sum of Subarray Minimums/README_EN.md +++ b/solution/0900-0999/0907.Sum of Subarray Minimums/README_EN.md @@ -37,7 +37,37 @@ Sum is 17. ## Solutions -### Solution 1 +### Solution 1: Monotonic Stack + +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. + +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)$. + +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. + +Let's take an example to illustrate. For the following array: + +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. + +``` +0 4 3 2 5 3 2 1 +* ^ * +``` + +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. + +``` +0 4 3 2 5 3 2 1 +* ^ * +``` + +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. + +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. + +Be aware of data overflow and modulo operations. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $arr$. @@ -264,61 +294,4 @@ impl Solution { -### Solution 2 - - - -```rust -const MOD: i64 = (1e9 as i64) + 7; - -impl Solution { - pub fn sum_subarray_mins(arr: Vec) -> i32 { - let n: usize = arr.len(); - let mut ret: i64 = 0; - let mut left: Vec = vec![-1; n]; - let mut right: Vec = vec![n as i32; n]; - // Index stack, store the index of the value in the given array - let mut stack: Vec = Vec::new(); - - // Find the first element that's less than the current value for the left side - // The default value of which is -1 - for i in 0..n { - while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] { - stack.pop(); - } - if !stack.is_empty() { - left[i] = *stack.last().unwrap(); - } - stack.push(i as i32); - } - - stack.clear(); - - // Find the first element that's less or equal than the current value for the right side - // The default value of which is n - for i in (0..n).rev() { - while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] { - stack.pop(); - } - if !stack.is_empty() { - right[i] = *stack.last().unwrap(); - } - stack.push(i as i32); - } - - // Traverse the array, to find the sum - for i in 0..n { - ret += - ((((right[i] - (i as i32)) * ((i as i32) - left[i])) as i64) * (arr[i] as i64)) % - MOD; - ret %= MOD; - } - - (ret % (MOD as i64)) as i32 - } -} -``` - - - diff --git a/solution/0900-0999/0907.Sum of Subarray Minimums/Solution2.rs b/solution/0900-0999/0907.Sum of Subarray Minimums/Solution2.rs deleted file mode 100644 index 88a984f333273..0000000000000 --- a/solution/0900-0999/0907.Sum of Subarray Minimums/Solution2.rs +++ /dev/null @@ -1,48 +0,0 @@ -const MOD: i64 = (1e9 as i64) + 7; - -impl Solution { - pub fn sum_subarray_mins(arr: Vec) -> i32 { - let n: usize = arr.len(); - let mut ret: i64 = 0; - let mut left: Vec = vec![-1; n]; - let mut right: Vec = vec![n as i32; n]; - // Index stack, store the index of the value in the given array - let mut stack: Vec = Vec::new(); - - // Find the first element that's less than the current value for the left side - // The default value of which is -1 - for i in 0..n { - while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] { - stack.pop(); - } - if !stack.is_empty() { - left[i] = *stack.last().unwrap(); - } - stack.push(i as i32); - } - - stack.clear(); - - // Find the first element that's less or equal than the current value for the right side - // The default value of which is n - for i in (0..n).rev() { - while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] { - stack.pop(); - } - if !stack.is_empty() { - right[i] = *stack.last().unwrap(); - } - stack.push(i as i32); - } - - // Traverse the array, to find the sum - for i in 0..n { - ret += - ((((right[i] - (i as i32)) * ((i as i32) - left[i])) as i64) * (arr[i] as i64)) % - MOD; - ret %= MOD; - } - - (ret % (MOD as i64)) as i32 - } -} diff --git a/solution/0900-0999/0908.Smallest Range I/README.md b/solution/0900-0999/0908.Smallest Range I/README.md index a493e95d34daa..183c44a6b6847 100644 --- a/solution/0900-0999/0908.Smallest Range I/README.md +++ b/solution/0900-0999/0908.Smallest Range I/README.md @@ -54,7 +54,13 @@ ## 解法 -### 方法一 +### 方法一:数学 + +根据题目描述,我们可以将数组中的最大值加上 $k$,最小值减去 $k$,这样可以使得数组中的最大值和最小值之差变小。 + +因此,最终的答案就是 $\max(nums) - \min(nums) - 2 \times k$。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 `nums` 的长度。空间复杂度 $O(1)$。 diff --git a/solution/0900-0999/0908.Smallest Range I/README_EN.md b/solution/0900-0999/0908.Smallest Range I/README_EN.md index 9ae2eec3b901f..2559d56b73a5e 100644 --- a/solution/0900-0999/0908.Smallest Range I/README_EN.md +++ b/solution/0900-0999/0908.Smallest Range I/README_EN.md @@ -50,7 +50,13 @@ ## Solutions -### Solution 1 +### Solution 1: Mathematics + +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. + +Therefore, the final answer is $\max(nums) - \min(nums) - 2 \times k$. + +The time complexity is $O(n)$, where $n$ is the length of the array `nums`. The space complexity is $O(1)$. diff --git a/solution/0900-0999/0910.Smallest Range II/README_EN.md b/solution/0900-0999/0910.Smallest Range II/README_EN.md index 63af3783968be..c7b1c5bdfa5d1 100644 --- a/solution/0900-0999/0910.Smallest Range II/README_EN.md +++ b/solution/0900-0999/0910.Smallest Range II/README_EN.md @@ -50,7 +50,13 @@ ## Solutions -### Solution 1 +### Solution 1: Greedy + Enumeration + +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. + +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. + +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.