leetcode-分割等和子集(416)

给定一个只包含正整数非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意:

  1. 每个数组中的元素不会超过 100
  2. 数组的大小不会超过 200

示例 1:

1
2
3
4
5
输入: [1, 5, 11, 5]

输出: true

解释: 数组可以分割成 [1, 5, 5] 和 [11].

示例 2:

1
2
3
4
5
输入: [1, 2, 3, 5]

输出: false

解释: 数组不能分割成两个元素和相等的子集.

思路

1
2
3
4
5
6
7
8
0-1 背包问题:

首先计算出dp[0][w] w:0 ~ target-1;
之后计算出dp[i][0] i:0 ~ 数组len-1

case 1 :vi == j+1 dp[i][j]=true;
case 2 :vi >j+1 dp[i][j]=dp[i-1][j];
case 3 :vi <j+1 dp[i][j]=dp[i-1][j] || dp[i-1][j-vi];

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Solution {
public boolean canPartition(int[] nums) {
int len = nums.length;
int total=0;
for(int i =0;i<len;i++){
total+=nums[i];
}
if(total%2==1){
return false;
}
int y=total/2;
boolean[][] dp = new boolean[len][y];
int temp =nums[0];
for(int i =0;i<y;i++){
dp[0][i]=(temp==(i+1));
}
boolean containOne=false;
for(int i =0;i<len;i++){
if(containOne){
}else{
if(nums[i]==1){
containOne=true;
}
}
dp[i][0]=containOne;
}
for(int i=1;i<len;i++){
int vi = nums[i];
for(int j=1;j<y;j++){
if(vi==(j+1)){
dp[i][j]=true;
}else if(vi > (j+1)){
dp[i][j]=dp[i-1][j];
}else{
dp[i][j]=dp[i-1][j]||dp[i-1][j-vi];
}
}
}
return dp[len-1][y-1];
}
}