递归应用-组合总和

给定一个正数数组和target, 求所有组合为target的解。

leetcode

直观解决方案是蛮力搜索,保存搜索路径,对于无法确定搜索次数的,只能使用递归搜索,准确描述搜索停止条件即可。

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> r = new ArrayList();
        combinationSum(candidates, target, new Stack<>(), r);
        return r;
    }

    
    
    public void combinationSum(int[] candidates, int target, Stack<Integer> s, List<List<Integer>> x) {

        if (target == 0) {
            x.add(s.stream().collect(Collectors.toList()));
            // System.out.println(s);
        }
        for(int i=0; i<candidates.length; ++i) {
            s.push(candidates[i]);
            int[] a = new int[candidates.length-i];
            System.arraycopy(candidates, i,  a, 0,candidates.length-i);
            combinationSum(a, y,  s, x);
            s.pop();
        }
    }
}

提前对输入数组排序,搜索过程中可剪枝

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> r = new ArrayList();
        combinationSum(candidates, target, new Stack<>(), r);
        return r;
    }
    
    
    public void combinationSum(int[] candidates, int target, Stack<Integer> s, List<List<Integer>> x) {

        if (target == 0) {
            x.add(s.stream().collect(Collectors.toList()));
            // System.out.println(s);
        }
        for(int i=0; i<candidates.length; ++i) {
            int y = target-candidates[i];	// 当搜索target小于0时,后续candidates可忽略
            if(y<0) break;

            s.push(candidates[i]);
            int[] a = new int[candidates.length-i];
            System.arraycopy(candidates, i,  a, 0,candidates.length-i);
            combinationSum(a, y,  s, x);
            s.pop();
        }
    }
}

若候选集中有重复的元素,为保证结果集中无重复组合,需对已搜索过的元素过滤掉,此外为保证结果集中一个元素只能出现一次,则在搜索候选集中去重当前元素

leecod

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> r = new ArrayList();
        combinationSum(candidates, target, new Stack<>(), r);
        return r;
    }

    public void combinationSum(int[] candidates, int target, Stack<Integer> s, List<List<Integer>> x) {

        if (target == 0) {
            x.add(s.stream().collect(Collectors.toList()));
            // System.out.println(s);
        }
        for(int i=0; i<candidates.length; ++i) {
            
            if(i>0 && candidates[i]==candidates[i-1]) continue;	//若候选集中有重复的元素skip,保证结果集中无重复组合

            int y = target-candidates[i];
            if(y<0) break;

            s.push(candidates[i]);
            int[] a = new int[candidates.length-i-1];
            System.arraycopy(candidates, i+1,  a, 0,candidates.length-i-1);	//候选集中不包含当前元素
            combinationSum(a, y,  s, x);
            s.pop();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值