LeetCode ยท #1425

Constrained Subsequence Sum Solution

Combine dynamic programming with a monotonic deque so each state can grab the best value from the last k positions in O(1).

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Hard

๐Ÿ”—

LeetCode

Problem #1425

๐Ÿ—๏ธ

Pattern

DP + Monotonic Deque

Pick a non-empty subsequence such that for every pair of consecutive chosen elements, their indices differ by at most k. Return the maximum possible sum.

Example
Input: nums = [10, 2, -10, 5, 20], k = 2 Output: 37 // Choose 10, 2, 5, 20
02
Section Two ยท Brute Force

Naive DP โ€” O(n ยท k)

Let dp[i] be the best subsequence sum ending at index i. Then look back over the previous k positions to find the best predecessor.

Problem: Scanning the last k states for every i costs O(nยทk). When both are large, that times out.
03
Section Three ยท Optimal

DP + Monotonic Deque โ€” O(n)

The recurrence is:

dp[i] = nums[i] + max(0, max(dp[j])) for j in [i-k, i-1]

So for each index, we only need the maximum dp value from the previous k indices. A decreasing deque gives that in O(1).

๐Ÿ’ก Mental model: Imagine every index wants advice from the strongest candidate in the last k seats. The deque keeps those candidates sorted by strength, so the best one is always at the front.
Algorithm
  • Remove indices from the front if they are more than k positions behind.
  • Compute dp[i] = nums[i] + max(0, dp[dq.front]) if the deque is non-empty.
  • Pop smaller or equal dp values from the back, because the new state dominates them.
  • Push i into the deque and update the global answer.
Why use max(0, ...)?:
  • A negative previous subsequence would only make the current sum worse.
  • In that case, start a fresh subsequence at i.
04
Section Four ยท Walkthrough

Visual Walkthrough

nums = [10, 2, -10, 5, 20], k = 2
Deque stores indices with decreasing dp values. i=0 โ†’ dp[0]=10, deque=[0] i=1 โ†’ dp[1]=2+10=12, deque=[1] i=2 โ†’ dp[2]=-10+12=2, deque=[1,2] i=3 โ†’ drop index 0 window-expired, dp[3]=5+12=17, deque=[3] i=4 โ†’ dp[4]=20+17=37, deque=[4] Best answer: 37 โœ“
05
Section Five ยท Code

Code โ€” Java & Python

Java โ€” DP + deque
import java.util.ArrayDeque; import java.util.Deque; class Solution { public int constrainedSubsetSum(int[] nums, int k) { int n = nums.length; int[] dp = new int[n]; Deque<Integer> dq = new ArrayDeque<>(); int ans = nums[0]; for (int i = 0; i < n; i++) { while (!dq.isEmpty() && dq.peekFirst() < i - k) dq.pollFirst(); dp[i] = nums[i] + (dq.isEmpty() ? 0 : Math.max(0, dp[dq.peekFirst()])); ans = Math.max(ans, dp[i]); while (!dq.isEmpty() && dp[dq.peekLast()] <= dp[i]) dq.pollLast(); dq.offerLast(i); } return ans; } }
Python โ€” DP + deque
from collections import deque class Solution: def constrainedSubsetSum(self, nums: list[int], k: int) -> int: n = len(nums) dp = [0] * n dq = deque() ans = nums[0] for i, num in enumerate(nums): while dq and dq[0] < i - k: dq.popleft() dp[i] = num + (0 if not dq else max(0, dp[dq[0]])) ans = max(ans, dp[i]) while dq and dp[dq[-1]] <= dp[i]: dq.pop() dq.append(i) return ans
06
Section Six ยท Analysis

Complexity Analysis

ApproachTimeSpace
Naive DPO(n ยท k)O(n)
DP + monotonic dequeO(n)O(n)
07
Section Seven ยท Edge Cases

Edge Cases & Pitfalls

CaseWhat happensWhy it matters
All numbers negativeReturn the largest single elementThe subsequence must be non-empty.
k = 1Only adjacent chaining allowedThe recurrence still works without changes.
Large positive streakDeque front keeps the strongest prior sumThis is where the O(n) optimization shines.
โš  Common Mistake: Forgetting to remove expired indices before reading the deque front. That lets states older than k illegally influence the answer.

โ† Back to Deque practice