Skip to content

Instantly share code, notes, and snippets.

@tatsuyax25
Created December 6, 2025 19:22
Show Gist options
  • Select an option

  • Save tatsuyax25/15efd61b8d0bee62e3d419cffcfa5ee2 to your computer and use it in GitHub Desktop.

Select an option

Save tatsuyax25/15efd61b8d0bee62e3d419cffcfa5ee2 to your computer and use it in GitHub Desktop.
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 num
/**
* Count the number of ways to partition nums into contiguous segments
* such that in each segment, max - min <= k.
*
* @param {number[]} nums - Input array of integers
* @param {number} k - Maximum allowed difference between max and min in a segment
* @return {number} - Number of valid partitions modulo 1e9+7
*/
var countPartitions = function (nums, k) {
const MOD = 1e9 + 7;
const n = nums.length;
// dp[i] = number of ways to partition the first i elements (nums[0..i-1])
const dp = Array(n + 1).fill(0);
// prefix[i] = sum of dp[0..i-1], used for fast range sum queries
// We allocate n+2 to avoid index issues when updating
const prefix = Array(n + 2).fill(0);
// Base case: empty prefix has 1 valid partition (no cuts)
dp[0] = 1;
prefix[1] = 1;
// Deques to maintain min and max in the current sliding window
let minDeque = []; // increasing order → front is min
let maxDeque = []; // decreasing order → front is max
// Left boundary of the current valid window
let left = 0;
// Iterate over array with right boundary
for (let right = 0; right < n; right++) {
// --- Update deques with nums[right] ---
// Maintain maxDeque (monotonic decreasing)
while (maxDeque.length && nums[maxDeque[maxDeque.length - 1]] <= nums[right]) {
maxDeque.pop();
}
maxDeque.push(right);
// Maintain minDeque (monotonic increasing)
while (minDeque.length && nums[minDeque[minDeque.length - 1]] >= nums[right]) {
minDeque.pop();
}
minDeque.push(right);
// --- Shrink window from the left until valid ---
// Condition: max - min <= k
while (nums[maxDeque[0]] - nums[minDeque[0]] > k) {
// If left index is leaving the window, pop it from deques
if (maxDeque[0] === left) maxDeque.shift();
if (minDeque[0] === left) minDeque.shift();
left++;
}
// --- DP transition ---
// dp[right+1] = sum of dp[j] for j in [left..right]
// Using prefix sums: prefix[right+1] - prefix[left]
dp[right + 1] = (prefix[right + 1] - prefix[left] + MOD) % MOD;
// Update prefix sum for next iteration
prefix[right + 2] = (prefix[right + 1] + dp[right + 1]) % MOD;
}
// Final answer: number of ways to partition the entire array
return dp[n];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment