leetcod 39组合总数

组合总数

注: 写这篇博客只是觉得自己记忆力不行,这道题很典型,剪枝实现,写成博客也只是为了每次看到能触发记忆点,提醒提醒自己。

题目描述:
  • 题目链接:https://leetcode-cn.com/problems/combination-sum
  • 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
  • candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

代码实现

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        dfs(candidates,0,target,new ArrayList<Integer>());
        return result;
    }
    private List<List<Integer>> result=new ArrayList();
    public void dfs(int[]candidates,int index,int target,List<Integer>list){
        if(target<0){
            return;
        }
        if(target==0){
            result.add(new ArrayList<Integer>(list));
        }else{
           /*
           * 设置索引index,并让i从index开始,是为了在凑target的时候能够避免重复组合的出现
           */
            for(int i=index;i<candidates.length;i++){
                 list.add(candidates[i]);
                 dfs(candidates,i,target-candidates[i],list); 
                 list.remove(list.size()-1);
            }
        }
    }
}

题目变体:求数字和为target有多少中组合

这则可以使用动态规划的方式来做,把题目看作一个背包问题:

  • i:代表可以使用的数字个数
  • j:代表当前所求的数字和target
 public static int combinationSum(int[] candidates, int target) {
	        Arrays.sort(candidates);
	        int n=candidates.length;
	        int[][]dp=new int[n+1][target+1];
	        for(int i=1;i<=n;i++){
	            for(int j=0;j<=target;j++){
	                if(j>=candidates[i-1])
	                    if(j==candidates[i-1]){
	                    //j==candidates[i-1]则代表当前目标和刚好等于candidates中的一个值,则dp[i][j]的值分为两部分:
	                    //a. 由 包含 candidates[i-1]的数字组合构成,其实就只有1种可能,即candidates[i-1] 本身
	                    //b. 由不包含candidates[i-1]元素的数字组合构成,即dp[i-1][j].
	                        dp[i][j]=dp[i-1][j]+1;                  
	                    }else
	                         dp[i][j]=dp[i-1][j]+dp[i][j-candidates[i-1]];
	                else{
	                    dp[i][j]=dp[i-1][j];
	                }
	            }
	        }
	        return dp[n][target];
	    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值