【动态规划】【01背包 装满背包有几种方法】Leetcode 494. 目标和
---------------🎈🎈 494. 目标和 题目链接🎈🎈-------------------
解法
动规五部曲
✒️确定dp数组以及下标的含义
dp[j] :表示容量为j的背包,装满,有dp[j]种方法
✒️确定递推公式⭐️ ⭐️ ⭐️
dp[j] += dp[j - nums[i]]
求装满背包有几种方法的情况下,都用这个递推公式!
✒️dp数组初始化
dp[0] = 1,因为如果nums[0],target = 0,那么此时应该是1
✒️确定遍历顺序
01背包问题,也就是每个元素只能取一次
此时外层正序遍历物品,内层逆序遍历背包
✒️举例推导dp数组
时间复杂度O(N)
空间复杂度O(N)
📘代码
class Solution {
public int findTargetSumWays(int[] nums, int target) {
// 动态规划
// 正数集合left 负数集合right
// sum(也就是nums的每个元素相加的综合)=》 left+right = sum
// 要想所有正数+ 所有负数 = target =》 left-right = target
// 即:left = (sum+target)/2 ————也就是如果nums[]中能凑出和为left的元素,那么result++
//【给定背包容量left,问有多少种方式可以将他装满】
// 【dp[j] : 装满容量为j的背包 有dp[j]种方法】
int sum = 0;
for(int num:nums){// 求总和sum
sum+=num;
}
// 如果(sum+target)/2 有余数,那么说明凑不出来,直接返回0
if((sum+target)%2 == 1) return 0;
// 如果target的绝对值大于sum,那么是没有方案的
if (Math.abs(target) > sum) return 0;
target = (sum+target)/2;
int[] dp = new int[target+1];
dp[0] = 1; //初始化背包容量为0时,有1种方法
for(int i = 0; i < nums.length; i++){ // 0-1背包正序遍历物品
for(int j = target; j >= nums[i]; j--){ // 0-1背包倒序遍历背包
// 【递推公式:dp[j] += dp[j-nums[i]]】
dp[j] += dp[j-nums[i]];
}
}
return dp[target];
}
}