NC46 加起来和为目标值的组合 算法java实现

题目描述

给出一组候选数\ C C 和一个目标数\ T T,找出候选数中起来和等于\ T T 的所有组合。
\ C C 中的每个数字在一个组合中只能使用一次。
注意:
给出一组候选数C 和一个目标数T,找出候选数中起来和等于T的所有组合。C中的每个数字在一个组合中只能使用一次。
注意:
题目中所有的数字(包括目标数\ T T )都是正整数
组合中的数字 (a_1, a_2, … , a_ka)要按非递增排序 (a_1<=a_2<= …<=a_ka )
结果中不能包含重复的组合
组合之间的排序按照索引从小到大依次比较,小的排在前面,如果索引相同的情况下数值相同,则比较下一个索引。
示例1
输入:[100,10,20,70,60,10,50],80
返回值:[[10,10,60],[10,20,50],[10,70],[20,60]]
说明:给定的候选数集是[100,10,20,70,60,10,50],目标数是80

代码思路

在一堆数字中找到符合某个条件的多个组合,且不重复,这种题的解法除了dfs回溯好像没有更好的方式了,得所有得情况都遍历,然后再判断哪些情况是可以跳过得,由于的出来得组合示例中是递增得(但不知道为何题目描述中又说非递增,然后组合间得排序规则示例也不满足,我没按索引排序也能通过,不知道为啥,可能是描述出错了??),所以得先给数组排个序,这里直接用Arrays.sort()直接排,应该没关系吧?毕竟这个题重点不是考排序算法,于是下面给出排举得思路:
假设已经排好序得情况下,数组为[10,10,20,50,60,70,100],80
那么我们就得先从第一个数字10开始,进行最深路径算法搜索,直到满足条件的最深为止,然后再逐步回溯,
10,10,20,50 …
10 10 50 60
10 10 60
10 20 50
10 50 60
10 60 70
10 70
10 100

第二个数字
以下结果跟上面的重复了。要跳过
10,20,50 符合
10,50,60 不符合退出
10,60,70 不符合 退出
10 70
10 100

第三个数字
20 50 60
20 60
20 70
20 100

第四个数字
50 60
50 70
50 100
第五个数字
60 70
60 100

第六个数字
100

代码实现

import java.util.*;
public class Solution {
    //测试用例
    //[],2 [100,10,20,70,60,10,50],80 [100,30,20,70,60,10,50],80 [100,10,50],80

    public ArrayList<ArrayList<Integer>> combinationSum2(int[] num, int target) {
      ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
      ArrayList<Integer> list=new ArrayList<Integer>();
      //因为结果集要从小到大排序,所以先给数组排个序
      Arrays.sort(num);
      dfs(0,num,target,list,res);
      return res;
    }
    
    public void dfs(int start,int[] num,int target,ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
       if(target==0){
           res.add(new ArrayList(list));
       }
        
        if(start>num.length){
            return;
        }
        
        for(int i=start;i<num.length;i++){
            if(i>start&&num[i]==num[i-1]) continue;
            if(target>=num[i]){
                list.add(num[i]);
                dfs(i+1,num,target-num[i],list,res);
                //不管是找到了还是没找到,都需要回溯一步,所以这里需要把末尾删掉
                list.remove(list.size()-1);
            }
        }
    }
    
    
   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值