update 0416.分割等和子集:修改文本错字,删除其他语言冗余代码

This commit is contained in:
Yuhao Ju
2022-12-20 16:32:29 +08:00
committed by GitHub
parent 363d4e6fcb
commit 4067790b7c

View File

@ -32,7 +32,7 @@
## 思路 ## 思路
这道题目初步看,如下两题几乎是一样的,大家可以用回溯法,解决如下两题 这道题目初步看,如下两题几乎是一样的,大家可以用回溯法,解决如下两题
* 698.划分为k个相等的子集 * 698.划分为k个相等的子集
* 473.火柴拼正方形 * 473.火柴拼正方形
@ -62,7 +62,7 @@
回归主题:首先,本题要求集合里能否出现总和为 sum / 2 的子集。 回归主题:首先,本题要求集合里能否出现总和为 sum / 2 的子集。
那么来一一对应一下本题,看看背包问题如来解决。 那么来一一对应一下本题,看看背包问题如来解决。
**只有确定了如下四点才能把01背包问题套到本题上来。** **只有确定了如下四点才能把01背包问题套到本题上来。**
@ -77,9 +77,9 @@
1. 确定dp数组以及下标的含义 1. 确定dp数组以及下标的含义
01背包中dp[j] 表示: 容量为j的背包所背的物品价值可以最大为dp[j]。 01背包中dp[j] 表示: 容量为j的背包所背的物品价值最大可以为dp[j]。
本题中每一个元素的数值是重量,也是价值。 本题中每一个元素的数值是重量,也是价值。
**套到本题dp[j]表示 背包总容量所能装的总重量是j放进物品后背的最大重量为dp[j]** **套到本题dp[j]表示 背包总容量所能装的总重量是j放进物品后背的最大重量为dp[j]**
@ -106,9 +106,9 @@
从dp[j]的定义来看首先dp[0]一定是0。 从dp[j]的定义来看首先dp[0]一定是0。
如果如果题目给的价值都是正整数那么非0下标都初始化为0就可以了如果题目给的价值有负数那么非0下标就要初始化为负无穷。 如果题目给的价值都是正整数那么非0下标都初始化为0就可以了如果题目给的价值有负数那么非0下标就要初始化为负无穷。
**这样才能让dp数组在递归公式的过程中取最大的价值,而不是被初始值覆盖了** **这样才能让dp数组在递的过程中取最大的价值,而不是被初始值覆盖了**
本题题目中 只包含正整数的非空数组所以非0下标的元素初始化为0就可以了。 本题题目中 只包含正整数的非空数组所以非0下标的元素初始化为0就可以了。
@ -202,15 +202,15 @@ class Solution {
if(nums == null || nums.length == 0) return false; if(nums == null || nums.length == 0) return false;
int n = nums.length; int n = nums.length;
int sum = 0; int sum = 0;
for(int num : nums){ for(int num : nums) {
sum += num; sum += num;
} }
//总和为奇数,不能平分 //总和为奇数,不能平分
if(sum % 2 != 0) return false; if(sum % 2 != 0) return false;
int target = sum / 2; int target = sum / 2;
int[] dp = new int[target + 1]; int[] dp = new int[target + 1];
for(int i = 0; i < n; i++){ for(int i = 0; i < n; i++) {
for(int j = target; j >= nums[i]; j--){ for(int j = target; j >= nums[i]; j--) {
//物品 i 的重量是 nums[i],其价值也是 nums[i] //物品 i 的重量是 nums[i],其价值也是 nums[i]
dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i]); dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i]);
} }
@ -220,6 +220,7 @@ class Solution {
} }
``` ```
二维数组版本(易于理解):
```java ```java
public class Solution { public class Solution {
public static void main(String[] args) { public static void main(String[] args) {
@ -288,46 +289,6 @@ false true false false false true true false false false false true
false true false false false true true false false false true true false true false false false true true false false false true true
``` ```
二维数组版本(易于理解):
```Java
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
if (sum % 2 == 1)
return false;
int target = sum / 2;
//dp[i][j]代表可装物品为0-i背包容量为j的情况下背包内容量的最大价值
int[][] dp = new int[nums.length][target + 1];
//初始化,dp[0][j]的最大价值nums[0](if j > weight[i])
//dp[i][0]均为0不用初始化
for (int j = nums[0]; j <= target; j++) {
dp[0][j] = nums[0];
}
//遍历物品,遍历背包
//递推公式:
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j <= target; j++) {
//背包容量可以容纳nums[i]
if (j >= nums[i]) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[nums.length - 1][target] == target;
}
}
```
### Python ### Python
```python ```python
class Solution: class Solution:
@ -341,6 +302,7 @@ class Solution:
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]) dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
return target == dp[target] return target == dp[target]
``` ```
### Go ### Go
```go ```go
// 分割等和子集 动态规划 // 分割等和子集 动态规划
@ -369,46 +331,6 @@ func canPartition(nums []int) bool {
} }
``` ```
```go
func canPartition(nums []int) bool {
/**
动态五部曲:
1.确定dp数组和下标含义
2.确定递推公式
3.dp数组初始化
4.dp遍历顺序
5.打印
**/
//确定和
var sum int
for _,v:=range nums{
sum+=v
}
if sum%2!=0{ //如果和为奇数,则不可能分成两个相等的数组
return false
}
sum/=2
//确定dp数组和下标含义
var dp [][]bool //dp[i][j] 表示: 前i个石头是否总和不大于J
//初始化数组
dp=make([][]bool,len(nums)+1)
for i,_:=range dp{
dp[i]=make([]bool,sum+1)
dp[i][0]=true
}
for i:=1;i<=len(nums);i++{
for j:=1;j<=sum;j++{//j是固定总量
if j>=nums[i-1]{//如果容量够用则可放入背包
dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i-1]]
}else{//如果容量不够用则不拿,维持前一个状态
dp[i][j]=dp[i-1][j]
}
}
}
return dp[len(nums)][sum]
}
```
### javaScript: ### javaScript:
```js ```js