.
This commit is contained in:
parent
dd039b771b
commit
b9ec60ea8f
109
src/arrays/3578CountPartWithMaxMinDiffAtMostk.rs
Normal file
109
src/arrays/3578CountPartWithMaxMinDiffAtMostk.rs
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
3578. Count Partitions With Max-Min Difference at Most K
|
||||
Solved
|
||||
Medium
|
||||
Topics
|
||||
premium lock iconCompanies
|
||||
Hint
|
||||
|
||||
You are given an integer array nums and an integer k. Your task is to partition nums into one or more non-empty contiguous segments such that in each segment, the difference between its maximum and minimum elements is at most k.
|
||||
|
||||
Return the total number of ways to partition nums under this condition.
|
||||
|
||||
Since the answer may be too large, return it modulo 109 + 7.
|
||||
|
||||
|
||||
|
||||
Example 1:
|
||||
|
||||
Input: nums = [9,4,1,3,7], k = 4
|
||||
|
||||
Output: 6
|
||||
|
||||
Explanation:
|
||||
|
||||
There are 6 valid partitions where the difference between the maximum and minimum elements in each segment is at most k = 4:
|
||||
|
||||
[[9], [4], [1], [3], [7]]
|
||||
[[9], [4], [1], [3, 7]]
|
||||
[[9], [4], [1, 3], [7]]
|
||||
[[9], [4, 1], [3], [7]]
|
||||
[[9], [4, 1], [3, 7]]
|
||||
[[9], [4, 1, 3], [7]]
|
||||
|
||||
Example 2:
|
||||
|
||||
Input: nums = [3,3,4], k = 0
|
||||
|
||||
Output: 2
|
||||
|
||||
Explanation:
|
||||
|
||||
There are 2 valid partitions that satisfy the given conditions:
|
||||
|
||||
[[3], [3], [4]]
|
||||
[[3, 3], [4]]
|
||||
|
||||
|
||||
|
||||
Constraints:
|
||||
|
||||
2 <= nums.length <= 5 * 104
|
||||
1 <= nums[i] <= 109
|
||||
0 <= k <= 109
|
||||
|
||||
|
||||
*/
|
||||
|
||||
pub fn count_partitions(nums: Vec<i32>, k: i32) -> i32 {
|
||||
type NType = u64;
|
||||
const MOD: NType = 1_000_000_007;
|
||||
let mut dp = vec![0 as NType; nums.len()];
|
||||
let mut left = 0usize;
|
||||
let mut min_q = std::collections::VecDeque::new();
|
||||
let mut max_q = std::collections::VecDeque::new();
|
||||
|
||||
for right in 0..nums.len() {
|
||||
while let Some(back) = min_q.pop_back() {
|
||||
if nums[back] <= nums[right] {
|
||||
min_q.push_back(back);
|
||||
break;
|
||||
}
|
||||
}
|
||||
min_q.push_back(right);
|
||||
|
||||
while let Some(back) = max_q.pop_back() {
|
||||
if nums[back] >= nums[right] {
|
||||
max_q.push_back(back);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
max_q.push_back(right);
|
||||
while let Some(max_to_pop) = max_q
|
||||
.front()
|
||||
.zip(min_q.front())
|
||||
.and_then(|(ma, mi)| (nums[*ma] - nums[*mi] > k).then_some(*ma < *mi))
|
||||
{
|
||||
let rm = if max_to_pop {
|
||||
max_q.pop_front()
|
||||
} else {
|
||||
min_q.pop_front()
|
||||
}
|
||||
.unwrap();
|
||||
left = left.max(rm + 1);
|
||||
}
|
||||
|
||||
let parts = dp[left.saturating_sub(1)..right].iter().sum::<NType>() % MOD;
|
||||
dp[right] = parts;
|
||||
if left == 0 {
|
||||
dp[right] = (dp[right] + 1) % MOD; // add one for the whole subarray being a partition
|
||||
}
|
||||
}
|
||||
dp.last().cloned().unwrap_or(0) as i32
|
||||
}
|
||||
#[test]
|
||||
fn test_count_collisions() {
|
||||
assert_eq!(count_partitions(vec![9, 4, 1, 3, 7], 4), 6);
|
||||
assert_eq!(count_partitions(vec![3, 3, 4], 0), 2);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user