Merge pull request #2084 from NeedyChild/patch-1

添加 0494.目标和.md Java版本的二维数组解法
This commit is contained in:
程序员Carl
2023-07-11 11:27:55 +08:00
committed by GitHub

View File

@ -292,6 +292,85 @@ class Solution {
}
```
易于理解的二维数组版本:
```java
class Solution {
public int findTargetSumWays(int[] nums, int target) {
// 01背包应用之“有多少种不同的填满背包最大容量的方法“
// 易于理解的二维数组解法及详细注释
int sum = 0;
for(int i = 0; i < nums.length; i++) {
sum += nums[i];
}
// 注意nums[i] >= 0的题目条件意味着sum也是所有nums[i]的绝对值之和
// 这里保证了sum + target一定是大于等于零的也就是left大于等于零毕竟我们定义left大于right
if(sum < Math.abs(target)){
return 0;
}
// 利用二元一次方程组将left用target和sum表示出来替换掉right组合详见代码随想录对此题的分析
// 如果所求的left数组和为小数则作为整数数组的nums里的任何元素自然是没有办法凑出这个小数的
if((sum + target) % 2 != 0) {
return 0;
}
int left = (sum + target) / 2;
// dp[i][j]遍历到数组第i个数时 left为j时的能装满背包的方法总数
int[][] dp = new int[nums.length][left + 1];
// 初始化最上行dp[0][j])当nums[0] == j时注意nums[0]和j都一定是大于等于零的因此不需要判断等于-j时的情况有唯一一种取法可取到jdp[0][j]此时等于1
// 其他情况dp[0][j] = 0
// java整数数组默认初始值为0
for(int j = 0; j <= left; j++) {
if(nums[0] == j) {
dp[0][j] = 1;
}
}
// 初始化最左列dp[i][0])
// 当从nums数组的索引0到i的部分有n个0时n > 0)每个0可以取+/-因此有2的n次方中可以取到j = 0的方案
// n = 0说明当前遍历到的数组部分没有0全为正数因此只有一种方案可以取到j = 0就是所有数都不取
int numZeros = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 0) {
numZeros++;
}
dp[i][0] = (int) Math.pow(2, numZeros);
}
// 递推公式分析:
// 当nums[i] > j时这时候nums[i]一定不能取所以是dp[i - 1][j]种方案数
// nums[i] <= j时num[i]可取可不取因此方案数是dp[i - 1][j] + dp[i - 1][j - nums[i]]
// 由递推公式可知先遍历i或j都可
for(int i = 1; i < nums.length; i++) {
for(int j = 1; j <= left; j++) {
if(nums[i] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
}
}
}
// 打印dp数组
// for(int i = 0; i < nums.length; i++) {
// for(int j = 0; j <= left; j++) {
// System.out.print(dp[i][j] + " ");
// }
// System.out.println("");
// }
return dp[nums.length - 1][left];
}
}
```
### Python
回溯版
```python