Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
- Each of the array element will not exceed 100.
- The array size will not exceed 200.
Example 1:
Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.
题意:将一个数组分成两个子数组,两个子数组各自累加的和能否相等。
思路:
首先将数组所有的和相加,如果和是奇数,则肯定不能满足题意;若和时偶数,就要考虑数组中的数是否能满足部分和等于总数和的一半,这是背包问题,并且所有的数只能被使用一次或者不使用。
创建一个大小为总数和/2的布尔数组dp= new boolean[sum/2 + 1],表示从0到sum/2每个数是否能由数组中的数拼凑而成。
如数组nums中有[1、2、4、5]四个数,则sum/2=6,则 dp = {true,true,true,true,true,true,true},表示0-6都能用nums数组中的数凑成。
判断dp[]中某个数target是否能够被拼凑成的具体方法是,分别遍历nums中的数num,然后看target是否拼凑成功,或者target-num是否拼凑成功,如果target-num拼凑成功,则target-num + num就能拼凑成功。
以nums中的数为例:当遍历到1时,dp = {true,true,false,false,false,false,false} (1能拼凑成1);
当遍历到2时,dp = {true,true,true,true,false,false,false} (2能拼凑成2, 1、2能拼凑成3);
当遍历到4时,dp = {true,true,true,true,true,true,false} (4能拼凑成4, 1、4能拼凑成5);
当遍历到5时,dp = {true,true,true,true,true,true,true} (1、6或2、4能拼凑成6);
代码:
class Solution {
public boolean canPartition(int[] nums) {
int sum =0;
for(int num : nums){
sum += num;
}
if(sum%2 == 1)
return false;
sum /= 2;
boolean[] dp = new boolean[sum+1];
dp[0] =true;
for(int num: nums){
for(int j=sum;j>=num;j--){
dp[j]=dp[j]||dp[j-num];
}
}
return dp[sum];
}
}