数据结构刷题(三十二):494.目标和、377. 组合总和 Ⅳ

一、494. 目标和

1.01背包问题

2.dp数组表示填满j(包括j)这么大容积的包,有dp[j]种方法。具体解释见代码

3.例如:dp[j],j 为5,

  • 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
  • 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
  • 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
  • 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
  • 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包
class Solution {
    public int findTargetSumWays(int[] nums, int target) {

        // 假设加法的总和为x,那么减法对应的总和就是sum - x。
        // 所以我们要求的是 x - (sum - x) = target。
        // x = (target + sum) / 2。
        // 此时问题就转化为,装满容量为x的背包(x就是背包容量),有几种方法。    注意加法和减法都是不带符号的。
        // 只要加法的总和x确定了target也就确定了
        int sum = 0;
        for (int i = 0; i < nums.length; i++)
            sum += nums[i];
        // 如果target过大 sum将无法满足
        if ( target < 0 && sum < -target) return 0;
        // 如果背包容量不为整数就无解了
        if ((target + sum) % 2 != 0) return 0;

        int size = (target + sum) / 2;
        if(size < 0) size = -size;
        // dp数组表示填满j(包括j)这么大容积的包,有dp[j]种方法
        int[] dp = new int[size + 1];
        // 这里的初始化可以理解成装满背包为0有1种组合方法
        dp[0] = 1;
        for (int i = 0; i < nums.length; i++) {
            for (int j = size; j >= nums[i]; j--) {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[size];

    }
}

二、377. 组合总和 Ⅳ

1.dp[i]: 凑成目标正整数为i的排列个数为dp[i]

2.本题因为是排列问题,所以需要将原先完全背包中的循环进行颠倒,先进行背包后物品,也就是先target后nums数组。即如果求排列数就是外层for遍历背包,内层for循环遍历物品

3.代码

class Solution {
    public int combinationSum4(int[] nums, int target) {

        // 如果求排列数就是外层for遍历背包,内层for循环遍历物品。
        // dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法
        int[] dp = new int[target + 1];
        // 这里的初始化与题目中说的定目标值是正整数有关
        dp[0] = 1;
        // 先背包  后物品
        for (int i = 0; i <= target; i++) {
            for (int j = 0; j < nums.length; j++){
                if (i >= nums[j]){
                    dp[i] += dp[i - nums[j]];
                }
            }
        }
        return dp[target];
    }
}

三、70. 爬楼梯

1.除了使用斐波那契,还可以使用完全背包来解决问题

class Solution {
    public int climbStairs(int n) {

        int[] dp =new int[n + 1];
        // 需要重新设定一个weight数组
        int[] weight = {1,2};
        dp[0] = 1;

        for (int i = 0; i <= n; i++) {
            for (int j = 0; j < weight.length; j++) {
                if (i >= weight[j]){
                    dp[i] += dp[i - weight[j]];
                }
            }
        }
    return dp[n];
    }
}

你可能感兴趣的:(力扣刷题,数据结构,算法,动态规划)