背包问题VI

来源:互联网 发布:实战java高并发程序设 编辑:程序博客网 时间:2024/06/11 02:39

背包问题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;    }}

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

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

原创粉丝点击