Leetcode Combination Sum I & II

Problem 1: Combination Sum I

Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The same repeated number may be chosen from C unlimited number of times.

Note: All numbers (including target) will be positive integers. Elements in a combination (a1, a2, � , ak) must be in non-descending order. (ie, a1 ? a2 ? � ? ak). The solution set must not contain duplicate combinations.

For example, given candidate set 2,3,6,7 and target 7, A solution set is: [7]  [2, 2, 3]

Solve the problem on leetcode

分析:

很像传统的硬币问题,我们同样运用Subset和Permutation的思路,只需要考虑两个问题:

1. 什么时候返回?

2. 递归的时候传入什么样的参数

对于上面第二点,我们不妨可以这么想,如果现在和为Target,此时取一个硬币,假设其值为v1,那么下一次,我们其实解决的是相同的子问题,只不过和变成了Target - v1 既然明确了第二点,我们就可以通过Target的取值来确定返回条件

1. 当Target < 0 的时候,无解,return

2. 当Target == 0 的时候,发现解,添加进res里面,然后return

代码如下:

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

需要注意的几点问题:

1.如果不用pos,从数组开头往数组尾巴扫,会出现什么问题? 会出现重复集合的问题,这里的重复不是指顺序完全相同的Set,而是对于每一种组合,我们输出一次就可以了 比如Sum = 3 不加pos会出现 [1,2],[2,1]两种一样的解,我们加入一个pos,限制每次添加只能再添加和这个数字相等或者比这个数字大的数字(数组之前sort过升序排列)这样就会避免问题


Problem 2 : Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. Each number in C may only be used once in the combination.

Note: All numbers (including target) will be positive integers. Elements in a combination (a1, a2, � , ak) must be in non-descending order. (ie, a1 ? a2 ? � ? ak). The solution set must not contain duplicate combinations.

For example, given candidate set 10,1,2,7,6,1,5 and target 8, A solution set is: [1, 7] [1, 2, 5] [2, 6] [1, 1, 6]

Solve the problem on leetcode

同样的思路,只需要注意几个问题:

1. 每个数字只能运用1次,所以再调用dfs的时候,传入的pos,应该是i + 1

2. 利用同样的思路来防止有重复的Set

while(i<num.length-1&&num[i]==num[i+1]) i++;

代码如下:

public class Solution {
    public ArrayList<ArrayList<Integer>> combinationSum2(int[] num, int target) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> tmp = new ArrayList<Integer>();
        Arrays.sort(num);
        dfs(res,tmp,num,target,0);
        return res;
    }
    
    public void dfs(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> tmp, int[] num, int target, int pos){
        if(target<0) return;
        if(target==0){
            res.add(new ArrayList<Integer>(tmp));
            return;
        }
        for(int i=pos; i<num.length;i++){
            tmp.add(num[i]);
            dfs(res,tmp,num,target-num[i],i+1);
            tmp.remove(tmp.size()-1);
            while(i<num.length-1&&num[i]==num[i+1]) i++;
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值