This commit is contained in:
hendrik 2025-12-06 21:33:24 +01:00
parent dd039b771b
commit b9ec60ea8f

View 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);
}