LeetCode 216. Combination Sum III(dfs)

216. Combination Sum III

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.

Note:

All numbers will be positive integers.
The solution set must not contain duplicate combinations.
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]]

题意

给定正整数k和正整数n,求所有的k个不同的1~9之间的正整数的组合,使得这k个数的和为n

思路

dfs, dfs递归方法的参数有4个,分别是:
num: k个正整数还剩下num个未确定
cur: 当前搜索到1~9中的哪一个数
target: 原来的n经过之前的搜索之后还剩target没有满足
list: 记录已经搜索的数字

最后是一点评论。大家一定都做过硬币找零问题,例如硬币找零–动态规划入门,硬币找零问题是一个经典的动态规划问题。大家也一定都知道,一般来说,一个问题如果既可以用动态规划求解又可以用深搜求解,用动态规划是更快的,因为动态规划可以保存中间计算的状态,避免子问题的重复计算。
那么问题是,为什么LeetCode上Combination Sum系列的题目要用深搜来解而经典的硬币找零问题可以用动态规划求解?原因在于Combination Sum要求数组中每个数只能使用一次,因此一个深搜里的一个状态(或者说是动态规划里的一个子问题),不仅包含num和target,还包含数组中的数是否使用的一个bitmap. 对于动态规划来说,这会造成子问题规模的爆炸。

代码

class Solution {
    private List<List<Integer>> ans = new ArrayList<List<Integer>>();
    
    public List<List<Integer>> combinationSum3(int k, int n) {
        if (n <= 0 || n > 45) {
            return ans;
        }
        dfs(k, 9, n, new LinkedList<Integer>());
        return ans;
    }
    
    private void dfs(int num, int cur, int target, LinkedList<Integer> list) {
        if (num == 0) {
            if (target == 0) {
                ans.add(new LinkedList(list));
            }
            return;
        }
        if (cur == 0) {
            return;
        }
        if (cur <= target) {
            list.add(cur);
            dfs(num-1, cur-1, target-cur, list);
            list.removeLast();
        }
        dfs(num, cur-1, target, list);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值