Skip to content

Commit

Permalink
Add problem 2104: Sum of Subarray Ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Aug 5, 2024
1 parent d28af3f commit 382c105
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,7 @@ pub mod problem_2096_step_by_step_directions_from_a_binary_tree_node_to_another;
pub mod problem_2099_find_subsequence_of_length_k_with_the_largest_sum;
pub mod problem_2100_find_good_days_to_rob_the_bank;
pub mod problem_2103_rings_and_rods;
pub mod problem_2104_sum_of_subarray_ranges;
pub mod problem_2108_find_first_palindromic_string_in_the_array;
pub mod problem_2109_adding_spaces_to_a_string;
pub mod problem_2110_number_of_smooth_descent_periods_of_a_stock;
Expand Down
24 changes: 24 additions & 0 deletions src/problem_2104_sum_of_subarray_ranges/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pub mod monotonic_stack;

pub trait Solution {
fn sub_array_ranges(nums: Vec<i32>) -> i64;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [
(&[1, 2, 3] as &[_], 4),
(&[1, 3, 3], 4),
(&[4, -2, -3, 4, 1], 59),
(&[-69, -70, -56, -83, 63], 694),
(&[0, 29, -52, -45, 41, -86, -9, 96, 73, -77], 6077),
];

for (nums, expected) in test_cases {
assert_eq!(S::sub_array_ranges(nums.to_vec()), expected);
}
}
}
82 changes: 82 additions & 0 deletions src/problem_2104_sum_of_subarray_ranges/monotonic_stack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::cmp::Ordering;

impl Solution {
pub fn sub_array_ranges(nums: Vec<i32>) -> i64 {
let mut min_stack = Vec::<(i32, u32)>::new();
let mut prev_min_length = 1;
let mut max_stack = Vec::<(i32, u32)>::new();
let mut iter = nums.into_iter();
let mut prev_max_length = 1;
let mut prev = iter.next().unwrap();
let mut sum = 0;
let mut result = 0;

for num in iter {
match num.cmp(&prev) {
Ordering::Less => {
max_stack.push((prev, prev_max_length));
prev_max_length = 1;

sum += u64::from((prev - num) as u32) * u64::from(prev_min_length);
prev_min_length += 1;

while let Some(&(top, top_length)) = min_stack.last() {
if num <= top {
sum += u64::from((top - num) as u32) * u64::from(top_length);
prev_min_length += top_length;
min_stack.pop();
} else {
break;
}
}
}
Ordering::Equal => {
prev_min_length += 1;
prev_max_length += 1;
}
Ordering::Greater => {
min_stack.push((prev, prev_min_length));
prev_min_length = 1;

sum += u64::from((num - prev) as u32) * u64::from(prev_max_length);
prev_max_length += 1;

while let Some(&(top, top_length)) = max_stack.last() {
if num >= top {
sum += u64::from((num - top) as u32) * u64::from(top_length);
prev_max_length += top_length;
max_stack.pop();
} else {
break;
}
}
}
}

prev = num;
result += sum;
}

result as _
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn sub_array_ranges(nums: Vec<i32>) -> i64 {
Self::sub_array_ranges(nums)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}

0 comments on commit 382c105

Please sign in to comment.