Combination Sum IV

You are given an array nums of distinct positive integers and a positive integer target.

Count the sequences of numbers taken from nums that add up exactly to target. Each number may be used any number of times, and order matters: (1, 2) and (2, 1) are two different sequences. Despite the traditional name, you are counting ordered sequences, not combinations.

Return that count. The tests guarantee it fits in a 32-bit signed integer.

Example 1

Input: nums = [1,3,4], target = 5 Output: 6 Why: The six sequences are (1,1,1,1,1), (1,1,3), (1,3,1), (3,1,1), (1,4) and (4,1).

Example 2

Input: nums = [5], target = 3 Output: 0 Why: Every sequence of 5s sums to a multiple of 5, so 3 cannot be reached.

Example 3

Input: nums = [2,3], target = 7 Output: 3 Why: The only multiset is {2, 2, 3}, and it can be arranged in 3 orders.

Constraints

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 1000
  • All values in nums are distinct.
  • 1 <= target <= 1000
  • The answer fits in a 32-bit signed integer.

Pattern Path · Dynamic Programming · problem 158 of 169

Focus on the last number of a sequence. If it is x, what must the rest of the sequence add up to?
Let ways(t) be the number of sequences summing to t. Then ways(t) is the sum of ways(t - x) over every x in nums with x <= t.
The empty sequence gives ways(0) = 1. Fill a table from 1 up to target, so each entry only reads smaller, already-finished entries.
Target: O(target · n) time, O(target) extra space.

Start simple

Recursively try every number as the next element until the remaining sum hits 0 or goes negative: exponential time, since the same remainders are recomputed over and over.

The key idea

Classify every valid sequence by its last element. If a sequence summing to t ends in x, removing that x leaves a sequence summing to t - x, and conversely any sequence for t - x plus a final x is a sequence for t. Different last elements give different sequences, so nothing is counted twice:

ways[t] = sum of ways[t - x] for each x in nums with x <= t, with ways[0] = 1 for the empty sequence.

Computing ways for t = 1, 2, ..., target in increasing order guarantees every value you read is already final. The answer is ways[target].

Note the loop order. Putting the target loop outside and the numbers loop inside lets any number appear in any position, which counts ordered sequences. Swapping the loops (numbers outside) would only allow numbers in the order they appear in nums, which counts unordered combinations instead, a different problem. The table has target + 1 entries and each looks at every number once, so the work is O(target · n).

Complexity

  • Time: O(target · n)
  • Space: O(target)

Python

class Solution:
    def combinationSum4(self, nums, target):
        # ways[t] = number of ordered sequences from nums that sum to t
        ways = [0] * (target + 1)
        ways[0] = 1                      # the empty sequence

        for t in range(1, target + 1):
            for x in nums:               # x is the last number of the sequence
                if x <= t:
                    ways[t] += ways[t - x]
        return ways[target]

JavaScript

var combinationSum4 = function(nums, target) {
  // ways[t] = number of ordered sequences from nums that sum to t
  const ways = new Array(target + 1).fill(0);
  ways[0] = 1;                        // the empty sequence

  for (let t = 1; t <= target; t++) {
    for (const x of nums) {           // x is the last number of the sequence
      if (x <= t) ways[t] += ways[t - x];
    }
  }
  return ways[target];
};

What the interviewer is checking

The interviewer checks whether you can derive a recurrence from a "last choice" argument, and whether you understand how loop order decides between counting permutations and combinations.

Mistakes to avoid

  • Swapping the loops, which counts unordered combinations instead of ordered sequences.
  • Starting with ways[0] = 0, which makes every count zero.
  • Plain recursion without memoisation, which is exponential.
  • Integer overflow in fixed-width languages on intermediate entries that are never used for the answer.

Follow-ups to expect

  • What if nums could contain negative numbers? (Infinite sequences; cap the length.)
  • How do you count unordered combinations? (Swap the loops.)
  • How would you list the sequences? (Backtracking; output can be huge.)

In real software

Counting the ways to compose a value from building blocks where order matters appears in tiling and step-climbing problems, in counting message encodings, and in analysing how many packet sequences fill a fixed-size frame.

Practice next

Next Post Previous Post
No Comment
Add Comment
comment url