leetcode combination sum dp solution

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 (a1a2, ..., 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] 

This is a mutation of subset sum problem. It has pseudo polynomial solution, which can be done in DP.

The problem can also be asked like: give sum n, and m different valued coins, how many ways can you make changes from these coins, order doesn't matter.



The easier version is to just output how many ways . just a few lines. the idea is the knapsack solution. time complexity O(n*target),space complexity O(target)

        public void combinationSum(int[] candidates, int target) {
        // Start typing your Java solution below
        // DO NOT write main() function
        int dp[]=new int[target+1];
        dp[0]=1;
        
        for(int i=0;i<candidates.length;i++)
        for(int s=0;s<target+1;s++){
            if(s>=candidates[i]) dp[s]=dp[s-candidates[i]]+dp[s];
        }
        System.out.println(dp[target]);
        return;
    }

The harder version is to output the subset candidates. still the same idea, just a few modifications. time complexity stays but space complexity increases.

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {
        // Start typing your Java solution below
        // DO NOT write main() function
        Hashtable h=new Hashtable<Integer,ArrayList<ArrayList<Integer>>>();
        
        Arrays.sort(candidates);   //not necessary, just to get the results in format
        ArrayList<Integer> m=new ArrayList<Integer>();
        ArrayList<ArrayList<Integer>> n=new ArrayList<ArrayList<Integer>>();
        n.add(m);
        h.put(0,n);
        ArrayList<ArrayList<Integer>> a,b,c;
        for(int i=0;i<candidates.length;i++)
        for(int s=1;s<target+1;s++){
            if(s>=candidates[i]&&h.containsKey(s-candidates[i])){
                a=new ArrayList<ArrayList<Integer>>();
                c=((ArrayList<ArrayList<Integer>>)(h.get(s-candidates[i])));
                for(ArrayList<Integer> x:c){
                        ArrayList<Integer> y=new ArrayList<Integer>(x); 
                        y.add(candidates[i]);
                        a.add(y);}//ugly just due to we can't modify collection while traversing
			if(h.containsKey(s)){ b=((ArrayList<ArrayList<Integer>>)(h.get(s))); b.addAll(a);} 
			else h.put(s,a);} } 
	return (ArrayList<ArrayList<Integer>>)h.get(target)==null?new ArrayList<ArrayList<Integer>>():(ArrayList<ArrayList<Integer>>)h.get(target);//still just for format }}

surely the harder version can be done by DFS or backtracking, which is easier for printing the result.

Let's do it using backtracking.

public class Solution {
    public ArrayList<ArrayList<Integer>> combinationSum(int[] a, int target) {
        // Start typing your Java solution below
        // DO NOT write main() function
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> l=new ArrayList<Integer>();
        Arrays.sort(a);
        solve(a,target,0,0,l,res);
        return res;
    }
    public void solve(int[] a, int target, int sum, int i, ArrayList<Integer> l, ArrayList<ArrayList<Integer>> res){
        if(sum==target){ res.add(l); return;}
        if(sum>target||i>=a.length) return;
        int n=0;
        while(n*a[i]+sum<=target){
            solve(a,target,sum+n*a[i],i+1,l,res);
            ArrayList<Integer> tmp=new ArrayList<Integer>(l);
            l=tmp;
            l.add(a[i]);
            n++;
            
        }
        return;
    }
    
}

if you are doing combinationSum2

public class Solution {
    public ArrayList<ArrayList<Integer>> combinationSum2(int[] a, int target) {
        // Start typing your Java solution below
        // DO NOT write main() function
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> l=new ArrayList<Integer>();
        Arrays.sort(a);
        solve(a,target,0,0,l,res);
        return res;
    }
    public void solve(int[] a, int target, int sum, int i, ArrayList<Integer> l, ArrayList<ArrayList<Integer>> res){
        if(sum==target){ res.add(l); return;}
        if(sum>target||i>=a.length) return;
        int n=0;
        int j=i;
        while(j<a.length&&a[j]==a[i]) j++;//diff
        while(n<=j-i){//diff
            solve(a,target,sum+n*a[i],j,l,res);//diff
            ArrayList<Integer> tmp=new ArrayList<Integer>(l);
            l=tmp;
            l.add(a[i]);
            n++;
            
        }
        return;
    }
    
}




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值