Skip to content

Commit 463b37c

Browse files
authored
feat: add rust solution to lc problem: No.0907 (doocs#1128)
1 parent 2ae1906 commit 463b37c

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

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

+51
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,57 @@ public:
183183
};
184184
```
185185
186+
### **Rust**
187+
188+
```rust
189+
const MOD: i64 = 1e9 as i64 + 7;
190+
191+
impl Solution {
192+
pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 {
193+
let n: usize = arr.len();
194+
let mut ret: i64 = 0;
195+
let mut left: Vec<i32> = vec![-1; n];
196+
let mut right: Vec<i32> = vec![n as i32; n];
197+
// Index stack, store the index of the value in the given array
198+
let mut stack: Vec<i32> = Vec::new();
199+
200+
// Find the first element that's less than the current value for the left side
201+
// The default value of which is -1
202+
for i in 0..n {
203+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] {
204+
stack.pop();
205+
}
206+
if !stack.is_empty() {
207+
left[i] = *stack.last().unwrap();
208+
}
209+
stack.push(i as i32);
210+
}
211+
212+
stack.clear();
213+
214+
// Find the first element that's less or equal than the current value for the right side
215+
// The default value of which is n
216+
for i in (0..n).rev() {
217+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] {
218+
stack.pop();
219+
}
220+
if !stack.is_empty() {
221+
right[i] = *stack.last().unwrap();
222+
}
223+
stack.push(i as i32);
224+
}
225+
226+
// Traverse the array, to find the sum
227+
for i in 0..n {
228+
ret += ((right[i] - i as i32) * (i as i32 - left[i])) as i64 * arr[i] as i64 % MOD;
229+
ret %= MOD;
230+
}
231+
232+
(ret % MOD as i64) as i32
233+
}
234+
}
235+
```
236+
186237
### **Go**
187238

188239
```go

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

+95
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,50 @@ Sum is 17.
3535

3636
## Solutions
3737

38+
The problem asks for the sum of the minimum values of each subarray, which is actually equivalent to finding the number of subarrays for each element $arr[i]$ where $arr[i]$ is the minimum, multiplying each by $arr[i]$, and then summing these products.
39+
40+
Thus, the focus of the problem is translated to finding the number of subarrays for which $arr[i]$ is the minimum.
41+
42+
For each $arr[i]$, we identify the first position $left[i]$ to its left that is smaller than $arr[i]$ and the first position $right[i]$ to its right that is less than or equal to $arr[i]$.
43+
44+
The number of subarrays where $arr[i]$ is the minimum can then be given by $(i - left[i]) \times (right[i] - i)$.
45+
46+
It's important to note why we are looking for the first position $right[i]$ that is less than or equal to $arr[i]$ and not less than $arr[i]$.
47+
48+
If we were to look for the first position less than $arr[i]$, we would end up double-counting.
49+
50+
For instance, consider the following array:
51+
52+
The element at index $3$ is $2$, and the first element less than $2$ to its left is at index $0$. If we find the first element less than $2$ to its right, we would end up at index $7$. That means the subarray interval is $(0, 7)$. Note that this is an open interval.
53+
54+
```
55+
0 4 3 2 5 3 2 1
56+
* ^ *
57+
```
58+
59+
If we calculate the subarray interval for the element at index $6$ using the same method, we would find that its interval is also $(0, 7)$.
60+
61+
```
62+
0 4 3 2 5 3 2 1
63+
* ^ *
64+
```
65+
66+
Therefore, the subarray intervals of the elements at index $3$ and $6$ are overlapping, leading to double-counting.
67+
68+
If we were to find the first element less than or equal to $arr[i]$ to its right, we wouldn't have this problem.
69+
70+
The subarray interval for the element at index $3$ would become $(0, 6)$ and for the element at index $6$ it would be $(0, 7)$, and these two are not overlapping.
71+
72+
To solve this problem, we just need to traverse the array.
73+
74+
For each element $arr[i]$, we use a monotonic stack to find its $left[i]$ and $right[i]$.
75+
76+
Then the number of subarrays where $arr[i]$ is the minimum can be calculated by $(i - left[i]) \times (right[i] - i)$. Multiply this by $arr[i]$ and sum these values for all $i$ to get the final answer.
77+
78+
Remember to take care of data overflow and modulus operation.
79+
80+
The time complexity is $O(n)$, where $n$ represents the length of the array $arr$.
81+
3882
<!-- tabs:start -->
3983

4084
### **Python3**
@@ -139,6 +183,57 @@ public:
139183
};
140184
```
141185
186+
### **Rust**
187+
188+
```rust
189+
const MOD: i64 = 1e9 as i64 + 7;
190+
191+
impl Solution {
192+
pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 {
193+
let n: usize = arr.len();
194+
let mut ret: i64 = 0;
195+
let mut left: Vec<i32> = vec![-1; n];
196+
let mut right: Vec<i32> = vec![n as i32; n];
197+
// Index stack, store the index of the value in the given array
198+
let mut stack: Vec<i32> = Vec::new();
199+
200+
// Find the first element that's less than the current value for the left side
201+
// The default value of which is -1
202+
for i in 0..n {
203+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] {
204+
stack.pop();
205+
}
206+
if !stack.is_empty() {
207+
left[i] = *stack.last().unwrap();
208+
}
209+
stack.push(i as i32);
210+
}
211+
212+
stack.clear();
213+
214+
// Find the first element that's less or equal than the current value for the right side
215+
// The default value of which is n
216+
for i in (0..n).rev() {
217+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] {
218+
stack.pop();
219+
}
220+
if !stack.is_empty() {
221+
right[i] = *stack.last().unwrap();
222+
}
223+
stack.push(i as i32);
224+
}
225+
226+
// Traverse the array, to find the sum
227+
for i in 0..n {
228+
ret += ((right[i] - i as i32) * (i as i32 - left[i])) as i64 * arr[i] as i64 % MOD;
229+
ret %= MOD;
230+
}
231+
232+
(ret % MOD as i64) as i32
233+
}
234+
}
235+
```
236+
142237
### **Go**
143238

144239
```go
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const MOD: i64 = 1e9 as i64 + 7;
2+
3+
impl Solution {
4+
pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 {
5+
let n: usize = arr.len();
6+
let mut ret: i64 = 0;
7+
let mut left: Vec<i32> = vec![-1; n];
8+
let mut right: Vec<i32> = vec![n as i32; n];
9+
// Index stack, store the index of the value in the given array
10+
let mut stack: Vec<i32> = Vec::new();
11+
12+
// Find the first element that's less than the current value for the left side
13+
// The default value of which is -1
14+
for i in 0..n {
15+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] {
16+
stack.pop();
17+
}
18+
if !stack.is_empty() {
19+
left[i] = *stack.last().unwrap();
20+
}
21+
stack.push(i as i32);
22+
}
23+
24+
stack.clear();
25+
26+
// Find the first element that's less or equal than the current value for the right side
27+
// The default value of which is n
28+
for i in (0..n).rev() {
29+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] {
30+
stack.pop();
31+
}
32+
if !stack.is_empty() {
33+
right[i] = *stack.last().unwrap();
34+
}
35+
stack.push(i as i32);
36+
}
37+
38+
// Traverse the array, to find the sum
39+
for i in 0..n {
40+
ret += ((right[i] - i as i32) * (i as i32 - left[i])) as i64 * arr[i] as i64 % MOD;
41+
ret %= MOD;
42+
}
43+
44+
(ret % MOD as i64) as i32
45+
}
46+
}

0 commit comments

Comments
 (0)