Framework Thinking - Neetcode 150 - Count Partitions With Max-Min Difference at Most K
Here is solutions for Count Partitions With Max-Min Difference at Most K.
1. Understand the problem
2. Clarify constraints, asks 4 - 5 questions including edge cases.
3. Explore examples.
4. Brainstorm 2 - 3 solutions, naive solution first and optimize later. Explain the key idea of each solution.
4.1. Backtracking - Time O(2^N * N), Space O(N)
Examples:
nums = [4,9,1,3,7]
=> Bactracking: [4], [4,9], [4,9,1], [4,9,1,3], [4,9,1,3,7]
class Solution:
def countPartitions(self, nums, k):
n = len(nums)
def backtrack(start):
# If we used the entire array, 1 valid partition
if start == n:
return 1
res = 0
cur_min = cur_max = nums[start]
for end in range(start, n):
cur_min = min(cur_min, nums[end])
cur_max = max(cur_max, nums[end])
if cur_max - cur_min <= k:
res += backtrack(end + 1)
else:
break # further expanding only increases diff
return res
return backtrack(0)
-
Time: O(2^N * N)
-
Space: O(N)
4.2. DP Top-down - Time O(N^2), Space O(N)
class Solution:
def countPartitions(self, nums, k):
n = len(nums)
dp = [0] * (n + 1)
dp[0] = 1 # empty prefix
for i in range(1, n + 1):
cur_min = cur_max = nums[i - 1]
# expand backwards: j → i-1
for j in range(i - 1, -1, -1):
cur_min = min(cur_min, nums[j])
cur_max = max(cur_max, nums[j])
if cur_max - cur_min <= k:
dp[i] += dp[j]
else:
break # too wide, will only get worse
return dp[n]
-
Time: O(N^2)
-
Space: O(N)
4.3. Max and Min Monotonic Queue, Prefix Sum of DP - Time O(N), Space O(N)
class Solution:
def countPartitions(self, nums, k):
from collections import deque
n = len(nums)
# dp[i] = number of ways to partition nums[0:i]
dp = [0] * (n + 1)
prefix = [0] * (n + 1)
dp[0] = 1
prefix[0] = 1
maxD = deque() # monotonic decreasing (store indices)
minD = deque() # monotonic increasing (store indices)
left = 0 # left boundary for valid window
for right in range(1, n + 1):
val = nums[right - 1]
# ---- maintain max deque ----
while maxD and nums[maxD[-1]] < val:
maxD.pop()
maxD.append(right - 1)
# ---- maintain min deque ----
while minD and nums[minD[-1]] > val:
minD.pop()
minD.append(right - 1)
# ---- shrink window until valid ----
while nums[maxD[0]] - nums[minD[0]] > k:
left += 1
if maxD[0] < left:
maxD.popleft()
if minD[0] < left:
minD.popleft()
# ---- DP transition using prefix sum ----
dp[right] = prefix[right - 1] - (prefix[left - 1] if left > 0 else 0)
prefix[right] = prefix[right - 1] + dp[right]
return dp[n] % (10**9 + 7)
-
Time: O(N)
-
Space: O(N)
Dry run ideas:
-
[9]
-
[9] [4]
-
[9] [4,1,3]
-
[9, 4, 1] [3, 7]
5. Implement solutions.
6. Dry run testcases.
December 7, 2025