Combination Sum IV

MediumDynamic Programming · Unbounded Knapsack (Ordered)🧩 Knapsack DPLeetCode #377 ↗Updated

Problem

You get an array of distinct positive integers nums and a number target. Count the sequences (numbers may repeat) whose elements add up to exactly target. Order matters: (1,2) and (2,1) are counted separately. The answer is guaranteed to fit in a 32-bit integer.
Inputnums = [1,2,3], target = 4Output7
Inputnums = [9], target = 3Output0

1 ≤ nums.length ≤ 200  ·  1 ≤ nums[i] ≤ 1000, all distinct  ·  1 ≤ target ≤ 1000  ·  Follow-up: what changes if negatives are allowed?

Try it yourself

Java
class Solution {
    public int combinationSum4(int[] nums, int target) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Decide the sequence one element at a time: the first number can be any x in nums, and the rest is the same question for target - x. So ways(t) = Σ ways(t - x) with ways(0) = 1 — the state is just the remaining sum.
PatternKnapsack DP

Instinct Choose items to hit or stay under a target sum (can it be done, best value, fewest items, how many ways) - index a DP array by the remaining capacity.

Memory hack Once? Walk back. Many? Walk forward. Each item used at most once loops capacity downward; reusable items loop it upward.

Open the Knapsack DP guide →

Approaches

Brute ForcePlain Recursion on Remaining Sum

Time O(nT/m)Space O(T/m)

From a remaining sum t, branch on every number that still fits and add up the counts of the branches. Reaching exactly 0 is one valid sequence. Each path in the tree is one ordered sequence, so the work is at least the answer itself (here m = smallest number).

Java
public int combinationSum4(int[] nums, int target) {
    if (target == 0) return 1; // one way: pick nothing more
    int count = 0;
    for (int x : nums) {
        if (x <= target) count += combinationSum4(nums, target - x);
    }
    return count;
}

Directly mirrors the definition, but explodes for any sizeable target.

At a glance

LevelApproachTimeSpace
Brute ForcePlain Recursion on Remaining SumO(nT/m)O(T/m)
BetterMemoized Recursion (Top-Down)O(T · n)O(T)
OptimalBottom-Up DP over SumsO(T · n)O(T)
Common pitfalls
  • Putting the nums loop outside — that counts unordered combinations, not sequences.
  • Forgetting dp[0] = 1 — every count then stays 0.
  • Using -1 as an “unset” marker while intermediate sums may overflow; a nullable cache avoids clashes.
Interview tips
  • Clarify early that order matters — it decides which loop goes outside.
  • Name the state: “number of sequences summing to t”; the transition follows.
  • Follow-up: with negatives, cycles like +1/−1 give infinitely many sequences, so a length limit is needed.
Pattern
Ordered unbounded knapsack → count sequences reaching a total when items repeat and order matters.
My notes saved in this browser