Leetcode 216: Combination Sum III

  • Total Accepted: 45842
  • Total Submissions: 115036
  • Difficulty: Medium

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

 

Example 1:

Input: k = 3, n = 7

Output:

[[1,2,4]]

Example 2:

Input: k = 3, n = 9

Output:

[[1,2,6], [1,3,5], [2,3,4]]
 
 
Code:
from math import ceil

class Solution(object):
    
    def lower_bound(self, n, k):
        return int(ceil(float(2*n+k**2-k)/(2*k)))

    def upper_bound(self, n, k):
        return n-k*(k-1)/2 + 1

    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """
        if k < 1 or k > 9 or n > (9 + (9 -k + 1)) * k / 2:
            return []

    	return list(self._comb_sum(n,k, 10))
    
    def _comb_sum(self, n, k, last_i):
    	if k == 1:
    		yield [n]
    	else:
        	for i in xrange(self.lower_bound(n, k), min(last_i, self.upper_bound(n, k))):
    		    for res in self._comb_sum(n-i, k-1, i):
    			    yield res + [i]

 

Idea:

I am using some mathematical properties to solve this problem.

(1) if k<1 or k>9 or the largest k numbers in 1~9 sum is larger less than n, then the program should return an empty list. (line 17-18)

(2) To solve this problem by recursion, we call `_comb_sum` recursively. It has `n`, `k` and `last_i` as parameters.  Intuitively, the function calls `n-i`, `k-1` in the recursion while traversing `i` in a designated range.

The lower bound of the traversal range is that: $latex \sum\limits_{j=i-k+1}^{i} j = \frac{(2i-k+1) \cdot k}{2} \geq n$. That is, the largest $latex k$ number ending at $latex i$ should sum up larger than $latex n$. Any $latex i$ smaller than that will result $latex n-i$ being too large to be summed up by $latex k-1$ numbers smaller than $latex i$. Solving this inequality we get: $latex i \geq \frac{2n+k^2-k}{2k}$.

The upper bound of the traversal range is that: $latex 1+2+\cdots+(k-1) + i \leq n$. If $latex i$ is larger than that, you can’t use remaining $latex k-1$ numbers to sum up to $latex n-i$. One more constraint is that the upper bound should not equal to/exceed $latex i$ from the upper level of recursion. 

 

Some people solve this problem by dfs: https://discuss.leetcode.com/topic/15023/accepted-recursive-java-solution-easy-to-understand/2https://discuss.leetcode.com/topic/15168/concise-python-solution-using-dfs

 

Although dfs is more readable, it wastes some time on unnecessary trials:

class Solution(object):
    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """
        if k < 1 or k > 9 or n > (9+9-k+1)*k/2:
            return []

        res = []    
        self.dfs(n, k, 1, [], res)
        return res

    def dfs(self, n, k, start, cur, res):
        if k == 0: 
            if n == 0:
                res.append(list(cur))
        else:
            for i in xrange(start, 10):
                cur.append(i)
                self.dfs(n-i, k-1, i+1, cur, res)
                cur.pop()

        

 

Note that at line 18 you should add a copy of `cur` to `res`. Otherwise any change in `cur` will change that added to `res`.

Leave a comment

Your email address will not be published. Required fields are marked *