背包问题VI

背包问题VI Lintcode 564

已知:

给出一个都是正整数的数组 nums,其中没有重复的数。从中找出所有的和为 target 的组合个数。

 - 一个数可以在组合中出现多次。
 - 数的顺序不同则会被认为是不同的组合。

示例:

给出 nums = [1, 2, 4], target = 4


[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[2, 1, 1]
[2, 2]
[4]


则返回6

思路:

注意题目描述中的“数的顺序不同则会被认为是不同的组合",也就是典型的动态规划问题。
以{1,2,4}为例, 要使得和为4, 则结果为第一个数为1的排列组合数 + 第一个数为2的排列组合数 + 第一个数为4的排列组合数。 终止条件是和小于数组的当前的数字(如果两者相同则返回1).

代码如下:

public class Solution {
    public int backPackVI(int[] nums, int target) {
        if (target == 0) {
            return 1;
        }
        if (target < 0) {
            return 0;
        }
        int ret = 0;
        for (int i : nums) {
                temp[target - i] = backPackVI(nums, target - i);
        }
        return ret;
    }
}

以上代码通过了大部分数据,但是最后两个数据的处理时间极长,但是数组长度仅仅为13. 其原因也很简单,动态规划本身只能作为一种思路,包含了诸多重复计算的内容,我们只需要用数组存储计算过的内容,如果未初始化,则先初始化,如果有值,则直接用来计算即可。
优化后的代码如下:

public class Solution {
//因为测试样例的target最大值为35,这个数组大小可以根据target进行改变
    int[] temp = new int[100]; 

    public int backPackVI(int[] nums, int target) {
        if (target == 0) {
            return 1;
        }
        if (target < 0) {
            return 0;
        }

//初始化为-1是因为默认为0
//如果数组为3,5 则1,2,4等数永远取不到,默认为0则不知道是否初始化过
        for (int i = 0; i < temp.length; i++) {
            temp[i] = -1;
        }

        int ret = 0;
        for (int i : nums) {
            //如果target - i小于0,不处理会出现数组越界异常
            if (target - i < 0) {
                continue;
            }
            //未初始化则进行初始化
            if (temp[target - i] == -1) {
                temp[target - i] = backPackVI(nums, target - i);
            }
            ret += temp[target - i];
        }
        return ret;
    }
}

运行速度大增,直接通过了所有测试案例.

谢谢您的阅读,希望对您有所帮助…φ(๑˃∀˂๑)♪

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值