LeetCode Combination Sum系列

Combination Sum系列
第一题是基础,给定一个数组和一个target,求有多少种组合可以加成target。运用回溯法,注意,每次add进结果里的数组需要new

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        List<Integer> temp=new ArrayList<>();
        Arrays.sort(candidates);
        helper(candidates,target,res,temp,0);
        return res;
    }
    public void helper(int[]nums,int target,List<List<Integer>> res,List<Integer>temp,int start){
        if(target==0){
            res.add(new ArrayList<Integer>(temp));
            return;
        }
          for(int i=start;i<nums.length;i++){
            if(nums[i]<=target){
                temp.add(nums[i]);
                helper(nums,target-nums[i],res,temp,i);
                temp.remove(temp.size()-1);
            }
            if(nums[i]>target){

                return;
            }
        }
    }
}

第二题,不能重复使用数组元素,添加去重条件

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        List<Integer> temp=new ArrayList<>();
        Arrays.sort(candidates);
        helper(candidates,target,res,temp,0);
        return res;
    }
    public void helper(int[]nums,int target,List<List<Integer>> res,List<Integer>temp,int start){
        if(target==0){
            res.add(new ArrayList<Integer>(temp));
            return;
        }
          for(int i=start;i<nums.length;i++){
            if (i > start && nums[i-1] == nums[i]) continue;//前一个等于后一个
            if(nums[i]<=target){
                temp.add(nums[i]);
                helper(nums,target-nums[i],res,temp,i+1);
                temp.remove(temp.size()-1);
            }
            if(nums[i]>target){               
                return;
            }
        }
    }
}

第三题,1-9中用k个数字加成n,类似上面,判断条件中加上元素个数判断

class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
    List<List<Integer>> ans = new ArrayList<>();
    combination(ans, new ArrayList<Integer>(), k, 1, n);
    return ans;
}

private void combination(List<List<Integer>> ans, List<Integer> comb, int k,  int start, int n) {
    if (comb.size() == k && n == 0) {
        List<Integer> li = new ArrayList<Integer>(comb);
        ans.add(li);
        return;
    }
    for (int i = start; i <= 9; i++) {
        comb.add(i);
        combination(ans, comb, k, i+1, n-i);
        comb.remove(comb.size() - 1);
    }
}
}

第四题与前三题都不太一样,因为不同的顺序也算一种,只需要输出结果数。

nums = [1, 2, 3]
target = 4

The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

使用递归,记忆数组加速,而且不需要start来标注起点。

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] memo=new int[target+1];
        Arrays.fill(memo,-1);
        return helper(nums,target,memo);
    }
    public int helper(int[]nums,int target,int[] memo){       
        if (target == 0) {
        return 1;
    }
        if(memo[target]!=-1){
            return memo[target];
        }
     int res = 0;
    for (int i = 0; i < nums.length; i++) {
        if (target >= nums[i]) {
            res += helper(nums, target - nums[i],memo);
        }
    }
    memo[target]=res;
    return res;
    }
}

回溯法要点在于确定一个起点,往下递归,递归完成后恢复成上一步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值