mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 02:53:31 +08:00
update 0416.分割等和子集:修改文本错字,删除其他语言冗余代码
This commit is contained in:
@ -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
|
||||||
|
Reference in New Issue
Block a user