给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
- 每个数组中的元素不会超过 100
- 数组的大小不会超过 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]; } }
|