Welcome to Subscribe On Youtube

216. Combination Sum III

Description

Find all valid combinations of k numbers that sum up to n such that the following conditions are true:

  • Only numbers 1 through 9 are used.
  • Each number is used at most once.

Return a list of all possible valid combinations. The list must not contain the same combination twice, and the combinations may be returned in any order.

 

Example 1:

Input: k = 3, n = 7
Output: [[1,2,4]]
Explanation:
1 + 2 + 4 = 7
There are no other valid combinations.

Example 2:

Input: k = 3, n = 9
Output: [[1,2,6],[1,3,5],[2,3,4]]
Explanation:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
There are no other valid combinations.

Example 3:

Input: k = 4, n = 1
Output: []
Explanation: There are no valid combinations.
Using 4 different numbers in the range [1,9], the smallest sum we can get is 1+2+3+4 = 10 and since 10 > 1, there are no valid combination.

 

Constraints:

  • 2 <= k <= 9
  • 1 <= n <= 60

Solutions

Solution 1

DFS.

This is a typical backtracking problem that explores all possible combinations to find those that meet the criteria.

Function Signature

def combinationSum3(self, k: int, n: int) -> List[List[int]]:
  • The function combinationSum3 takes two arguments: k, the number of digits in each combination, and n, the target sum.
  • It returns a list of lists, where each inner list is a combination of k digits that add up to n.

The dfs (Depth-First Search) Helper Function

def dfs(start, s, t): # s: sum, t: list
  • dfs is a recursive helper function defined within combinationSum3. It is used to perform a depth-first search to explore all possible combinations.
  • start: The starting point for the current exploration, ensuring that only numbers greater than start are considered to avoid repeats and maintain uniqueness.
  • s: The current sum of the numbers in the temporary list t.
  • t: A temporary list that stores the current combination being explored.

The Recursive Exploration

  • The recursion starts with dfs(1, 0, []), meaning the search begins with the number 1, the current sum as 0, and an empty list for the combination.
  • The base case of the recursion checks if the current sum s exceeds n or if the length of the temporary list t exceeds k. If either condition is true, the recursion returns, as the current path cannot yield a valid combination.
  • Another base case checks if s == n and len(t) == k. If both conditions are met, a valid combination is found, and a copy of t is added to the answer list ans. The copy is used because t is modified in subsequent steps.
  • The recursive step iterates from start to 9 (inclusive of 1 and exclusive of 10 because we’re dealing with digits). For each number i in this range, it is added to t, and dfs is called recursively with the updated parameters: the next starting number (i + 1), the new sum (s + i), and the updated temporary list t. After the recursive call returns, t.pop() is called to backtrack, removing the last number added to t and exploring other possibilities.

Collecting and Returning the Answer

  • ans is initialized as an empty list. It collects all valid combinations found during the depth-first search.
  • After exploring all possibilities through recursive backtracking, ans is returned, containing all combinations of k numbers that sum to n.

Solution 2: Binary Enumeration

We can use a binary integer of length $9$ to represent the selection of numbers $1$ to $9$, where the $i$-th bit of the binary integer represents whether the number $i + 1$ is selected. If the $i$-th bit is $1$, it means that the number $i + 1$ is selected, otherwise, it means that the number $i + 1$ is not selected.

We enumerate binary integers in the range of $[0, 2^9)$. For the currently enumerated binary integer $mask$, if the number of $1$s in the binary representation of $mask$ is $k$, and the sum of the numbers corresponding to $1$ in the binary representation of $mask$ is $n$, it means that the number selection scheme corresponding to $mask$ is a group of answers. We can add the number selection scheme corresponding to $mask$ to the answer.

The time complexity is $O(2^9 \times 9)$, and the space complexity is $O(k)$.

Similar problems:

Solution 3: Bit Manipulation

This implementation uses bit manipulation. It traverses the relevant values and updates its state as each value is processed. After all required states have been considered, the maintained result is returned.

  • class Solution {
        private List<List<Integer>> ans = new ArrayList<>();
        private List<Integer> t = new ArrayList<>();
        private int k;
    
        public List<List<Integer>> combinationSum3(int k, int n) {
            this.k = k;
            dfs(1, n);
            return ans;
        }
    
        private void dfs(int i, int s) {
            if (s == 0) {
                if (t.size() == k) {
                    ans.add(new ArrayList<>(t));
                }
                return;
            }
            if (i > 9 || i > s || t.size() >= k) {
                return;
            }
            t.add(i);
            dfs(i + 1, s - i);
            t.remove(t.size() - 1);
            dfs(i + 1, s);
        }
    }
    
    
    // Solution 2
    class Solution {
        private List<List<Integer>> ans = new ArrayList<>();
        private List<Integer> t = new ArrayList<>();
        private int k;
    
        public List<List<Integer>> combinationSum3(int k, int n) {
            this.k = k;
            dfs(1, n);
            return ans;
        }
    
        private void dfs(int i, int s) {
            if (s == 0) {
                if (t.size() == k) {
                    ans.add(new ArrayList<>(t));
                }
                return;
            }
            if (i > 9 || i > s || t.size() >= k) {
                return;
            }
            for (int j = i; j <= 9; ++j) {
                t.add(j);
                dfs(j + 1, s - j);
                t.remove(t.size() - 1);
            }
        }
    }
    
    
    
    // Solution 3
    class Solution {
        public List<List<Integer>> combinationSum3(int k, int n) {
            List<List<Integer>> ans = new ArrayList<>();
            for (int mask = 0; mask < 1 << 9; ++mask) {
                if (Integer.bitCount(mask) == k) {
                    List<Integer> t = new ArrayList<>();
                    int s = 0;
                    for (int i = 0; i < 9; ++i) {
                        if ((mask >> i & 1) == 1) {
                            s += (i + 1);
                            t.add(i + 1);
                        }
                    }
                    if (s == n) {
                        ans.add(t);
                    }
                }
            }
            return ans;
        }
    }
    
    
  • class Solution {
    public:
        vector<vector<int>> combinationSum3(int k, int n) {
            vector<vector<int>> ans;
            vector<int> t;
            function<void(int, int)> dfs = [&](int i, int s) {
                if (s == 0) {
                    if (t.size() == k) {
                        ans.emplace_back(t);
                    }
                    return;
                }
                if (i > 9 || i > s || t.size() >= k) {
                    return;
                }
                t.emplace_back(i);
                dfs(i + 1, s - i);
                t.pop_back();
                dfs(i + 1, s);
            };
            dfs(1, n);
            return ans;
        }
    };
    
    
    // Solution 2
    class Solution {
    public:
        vector<vector<int>> combinationSum3(int k, int n) {
            vector<vector<int>> ans;
            vector<int> t;
            function<void(int, int)> dfs = [&](int i, int s) {
                if (s == 0) {
                    if (t.size() == k) {
                        ans.emplace_back(t);
                    }
                    return;
                }
                if (i > 9 || i > s || t.size() >= k) {
                    return;
                }
                for (int j = i; j <= 9; ++j) {
                    t.emplace_back(j);
                    dfs(j + 1, s - j);
                    t.pop_back();
                }
            };
            dfs(1, n);
            return ans;
        }
    };
    
    
    
    // Solution 3
    class Solution {
    public:
        vector<vector<int>> combinationSum3(int k, int n) {
            vector<vector<int>> ans;
            for (int mask = 0; mask < 1 << 9; ++mask) {
                if (__builtin_popcount(mask) == k) {
                    int s = 0;
                    vector<int> t;
                    for (int i = 0; i < 9; ++i) {
                        if (mask >> i & 1) {
                            t.push_back(i + 1);
                            s += i + 1;
                        }
                    }
                    if (s == n) {
                        ans.emplace_back(t);
                    }
                }
            }
            return ans;
        }
    };
    
    
  • class Solution:
        def combinationSum3(self, k: int, n: int) -> List[List[int]]:
            def dfs(start, s, t): # s: sum, t: list
                if s > n or len(t) > k:
                    return
                if s == n and len(t) == k:
                    ans.append(t.copy())
                    return
    
                for i in range(start, 10):
                    t.append(i)
                    dfs(i + 1, s + i, t)
                    t.pop()
    
            ans = []
            dfs(1, 0, [])
            return ans
    
    
    # Solution 2
    class Solution:
        def combinationSum3(self, k: int, n: int) -> List[List[int]]:
            def dfs(i: int, s: int):
                if s == 0:
                    if len(t) == k:
                        ans.append(t[:])
                    return
                if i > 9 or i > s or len(t) >= k:
                    return
                for j in range(i, 10):
                    t.append(j)
                    dfs(j + 1, s - j)
                    t.pop()
    
            ans = []
            t = []
            dfs(1, n)
            return ans
    
    
    
    # Solution 3
    class Solution:
        def combinationSum3(self, k: int, n: int) -> List[List[int]]:
            ans = []
            for mask in range(1 << 9):
                if mask.bit_count() == k:
                    t = [i + 1 for i in range(9) if mask >> i & 1]
                    if sum(t) == n:
                        ans.append(t)
            return ans
    
    
  • func combinationSum3(k int, n int) (ans [][]int) {
    	t := []int{}
    	var dfs func(i, s int)
    	dfs = func(i, s int) {
    		if s == 0 {
    			if len(t) == k {
    				ans = append(ans, slices.Clone(t))
    			}
    			return
    		}
    		if i > 9 || i > s || len(t) >= k {
    			return
    		}
    		t = append(t, i)
    		dfs(i+1, s-i)
    		t = t[:len(t)-1]
    		dfs(i+1, s)
    	}
    	dfs(1, n)
    	return
    }
    
    
    // Solution 2
    func combinationSum3(k int, n int) (ans [][]int) {
    	t := []int{}
    	var dfs func(i, s int)
    	dfs = func(i, s int) {
    		if s == 0 {
    			if len(t) == k {
    				ans = append(ans, slices.Clone(t))
    			}
    			return
    		}
    		if i > 9 || i > s || len(t) >= k {
    			return
    		}
    		for j := i; j <= 9; j++ {
    			t = append(t, j)
    			dfs(j+1, s-j)
    			t = t[:len(t)-1]
    		}
    	}
    	dfs(1, n)
    	return
    }
    
    
    
    // Solution 3
    func combinationSum3(k int, n int) (ans [][]int) {
    	for mask := 0; mask < 1<<9; mask++ {
    		if bits.OnesCount(uint(mask)) == k {
    			t := []int{}
    			s := 0
    			for i := 0; i < 9; i++ {
    				if mask>>i&1 == 1 {
    					s += i + 1
    					t = append(t, i+1)
    				}
    			}
    			if s == n {
    				ans = append(ans, t)
    			}
    		}
    	}
    	return
    }
    
    
  • function combinationSum3(k: number, n: number): number[][] {
        const ans: number[][] = [];
        const t: number[] = [];
        const dfs = (i: number, s: number) => {
            if (s === 0) {
                if (t.length === k) {
                    ans.push(t.slice());
                }
                return;
            }
            if (i > 9 || i > s || t.length > k) {
                return;
            }
            t.push(i);
            dfs(i + 1, s - i);
            t.pop();
            dfs(i + 1, s);
        };
        dfs(1, n);
        return ans;
    }
    
    
    // Solution 2
    function combinationSum3(k: number, n: number): number[][] {
        const ans: number[][] = [];
        const t: number[] = [];
        const dfs = (i: number, s: number) => {
            if (s === 0) {
                if (t.length === k) {
                    ans.push(t.slice());
                }
                return;
            }
            if (i > 9 || i > s || t.length >= k) {
                return;
            }
            for (let j = i; j <= 9; ++j) {
                t.push(j);
                dfs(j + 1, s - j);
                t.pop();
            }
        };
        dfs(1, n);
        return ans;
    }
    
    
    
    // Solution 3
    function combinationSum3(k: number, n: number): number[][] {
        const ans: number[][] = [];
        for (let mask = 0; mask < 1 << 9; ++mask) {
            if (bitCount(mask) === k) {
                const t: number[] = [];
                let s = 0;
                for (let i = 0; i < 9; ++i) {
                    if (mask & (1 << i)) {
                        t.push(i + 1);
                        s += i + 1;
                    }
                }
                if (s === n) {
                    ans.push(t);
                }
            }
        }
        return ans;
    }
    
    function bitCount(i: number): number {
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }
    
    
  • public class Solution {
        private List<IList<int>> ans = new List<IList<int>>();
        private List<int> t = new List<int>();
        private int k;
    
        public IList<IList<int>> CombinationSum3(int k, int n) {
            this.k = k;
            dfs(1, n);
            return ans;
        }
    
        private void dfs(int i, int s) {
            if (s == 0) {
                if (t.Count == k) {
                    ans.Add(new List<int>(t));
                }
                return;
            }
            if (i > 9 || i > s || t.Count >= k) {
                return;
            }
            t.Add(i);
            dfs(i + 1, s - i);
            t.RemoveAt(t.Count - 1);
            dfs(i + 1, s);
        }
    }
    
    
    // Solution 2
    public class Solution {
        private List<IList<int>> ans = new List<IList<int>>();
        private List<int> t = new List<int>();
        private int k;
    
        public IList<IList<int>> CombinationSum3(int k, int n) {
            this.k = k;
            dfs(1, n);
            return ans;
        }
    
        private void dfs(int i, int s) {
            if (s == 0) {
                if (t.Count == k) {
                    ans.Add(new List<int>(t));
                }
                return;
            }
            if (i > 9 || i > s || t.Count >= k) {
                return;
            }
            for (int j = i; j <= 9; ++j) {
                t.Add(j);
                dfs(j + 1, s - j);
                t.RemoveAt(t.Count - 1);
            }
        }
    }
    
    
    
    // Solution 3
    public class Solution {
        public IList<IList<int>> CombinationSum3(int k, int n) {
            List<IList<int>> ans = new List<IList<int>>();
            for (int mask = 0; mask < 1 << 9; ++mask) {
                if (bitCount(mask) == k) {
                    List<int> t = new List<int>();
                    int s = 0;
                    for (int i = 0; i < 9; ++i) {
                        if ((mask >> i & 1) == 1) {
                            s += i + 1;
                            t.Add(i + 1);
                        }
                    }
                    if (s == n) {
                        ans.Add(t);
                    }
                }
            }
            return ans;
        }
    
        private int bitCount(int x) {
            int cnt = 0;
            while (x > 0) {
                x -= x & -x;
                ++cnt;
            }
            return cnt;
        }
    }
    
    
  • impl Solution {
        #[allow(dead_code)]
        pub fn combination_sum3(k: i32, n: i32) -> Vec<Vec<i32>> {
            let mut ret = Vec::new();
            let mut candidates = (1..=9).collect();
            let mut cur_vec = Vec::new();
            Self::dfs(n, k, 0, 0, &mut cur_vec, &mut candidates, &mut ret);
            ret
        }
    
        #[allow(dead_code)]
        fn dfs(
            target: i32,
            length: i32,
            cur_index: usize,
            cur_sum: i32,
            cur_vec: &mut Vec<i32>,
            candidates: &Vec<i32>,
            ans: &mut Vec<Vec<i32>>
        ) {
            if cur_sum > target || cur_vec.len() > (length as usize) {
                // No answer for this
                return;
            }
            if cur_sum == target && cur_vec.len() == (length as usize) {
                // We get an answer
                ans.push(cur_vec.clone());
                return;
            }
            for i in cur_index..candidates.len() {
                cur_vec.push(candidates[i]);
                Self::dfs(target, length, i + 1, cur_sum + candidates[i], cur_vec, candidates, ans);
                cur_vec.pop().unwrap();
            }
        }
    }
    
    
  • function combinationSum3(k, n) {
        const ans = [];
        const t = [];
        const dfs = (i, s) => {
            if (s === 0) {
                if (t.length === k) {
                    ans.push(t.slice());
                }
                return;
            }
            if (i > 9 || i > s || t.length >= k) {
                return;
            }
            t.push(i);
            dfs(i + 1, s - i);
            t.pop();
            dfs(i + 1, s);
        };
        dfs(1, n);
        return ans;
    }
    
    
    // Solution 2
    function combinationSum3(k, n) {
        const ans = [];
        const t = [];
        const dfs = (i, s) => {
            if (s === 0) {
                if (t.length === k) {
                    ans.push(t.slice());
                }
                return;
            }
            if (i > 9 || i > s || t.length >= k) {
                return;
            }
            for (let j = i; j <= 9; ++j) {
                t.push(j);
                dfs(j + 1, s - j);
                t.pop();
            }
        };
        dfs(1, n);
        return ans;
    }
    
    
    
    // Solution 3
    function combinationSum3(k, n) {
        const ans = [];
        for (let mask = 0; mask < 1 << 9; ++mask) {
            if (bitCount(mask) === k) {
                const t = [];
                let s = 0;
                for (let i = 0; i < 9; ++i) {
                    if (mask & (1 << i)) {
                        t.push(i + 1);
                        s += i + 1;
                    }
                }
                if (s === n) {
                    ans.push(t);
                }
            }
        }
        return ans;
    }
    
    function bitCount(i) {
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }
    
    

All Problems

All Solutions