leetcode_middle_35_377. Combination Sum IV

题意:

给定一个不重复的正整数数组和一个正整数,找出数组的数相加等于这个正整数的可能组合数。(组合中的数字可以重复,可以不必使用所有数组的数,不同顺序各算一种)

分析:

我们要得出之和的可能数,就是要搜索哪些组合的和是目标数。构造一棵树,递归搜索:(能得到正确答案,但是超时)

比如对于[1,2,3]目标数是4

                                              4

                   3 (4-1)        2 (4-2)         1(4-3)

            2      1     0              1    0   -1               0 -1  -2

 以此类推,小于等于零的时候返回,等于零的就是我们要的。

超时算法:

public class Solution {
    int count = 0;
    int nums[];
    public int combinationSum4(int[] nums, int target) {
        this.nums = nums;
        helper(target);
        return count;
    }
    
    private void helper(int sum){
        if(sum <= 0){
            if(sum == 0){
                count++;
            }
            return;
        }
        
        for(int i=0; i<nums.length; i++){
            helper(sum - nums[i]);
        }
    }
}

那么我们尝试题目标签的动态规划法,其实和递归搜索一样都是一种思想

动态规划的每一个结点也等于下一层的节点的和。

比如:                                            4

                   3 (4-1)        2 (4-2)         1(4-3)

target为4的值就等于target为3,2,1的值的和。(因为数组有1,2,3),target每向下一层就减去一个数组的值,减去数组的值1,2,3结果分别为3,2,1,就是第二层的所有结点。

第一层根节点(4)的值就是下一层所有子树(3,2,1)的值的和。

当选定1,2,3的时候就好像是排列组合的第一位被确定了。

和为4所有的情况:第一位为1,剩下3的情况数

                                  第一位为2,剩下2的情况数

                                  第一位为3,剩下1的情况数

public class Solution {
public int combinationSum4(int[] nums, int target) {
    int[] dp = new int[target+1];      //数组每一位代表一个结点,结点值是对应target对应的组合数
    int sum = 0;
    dp[0] = 1;
    for(int i=1; i<dp.length; i++){                               //纵向遍历每一层,i代表target
        for(int j=0; j<nums.length; j++){                         //横向遍历某一层
                if (i - nums[j] >= 0)                             //大于等于0的是有效的节点,否则是无效的结点
                    sum += dp[i - nums[j]];                       //这一层所有的(有效的)结点(代表的子树)的值的和就是这一层父节点的值
            }
            dp[i] =  sum;
            sum = 0;
        }
    return dp[target];
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值