题目:
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.
分析:
class Solution {
public boolean canPartition(int[] nums) {
//给定数组,求是否能将数组中分为两个子串,其和相等
//思路:经典的背包问题,只需要判断和是否为奇数,则直接返回false,若为偶数,则对sum/2一半的容量进行背包(因为每个数只能用一次,所以是01背包问题)求解
if(nums==null||nums.length==0) return false;
int sum=0;
for(int num:nums){
sum+=num;
}
if(sum%2==1){
//奇数
return false;
}
//偶数的情况(0,1背包)
int [] dp=new int[sum/2+1];
dp[0]=0;
sum=sum>>1;
for(int i=0;i<nums.length;i++){
//提前判断
if(nums[i]>sum) return false;
if(nums[i]==sum) return true;
for(int j=sum;j>=1;j--){
if(j>=nums[i]){
//判断是否能凑成满足条件的结果
dp[j]=Math.max(dp[j],nums[i]+dp[j-nums[i]]);
}
}
}
return dp[sum]==sum?true:false;
}
}
分析2(递归实现-易理解):
class Solution {
public boolean canPartition(int[] nums) {
//采用类似对子集求和递归求解,首先对字符串排序,之后直接从最后面开始拿一个数进行判断
//因为数已经排序,如果remain的<0说明,前面的数更不满足
if(nums==null||nums.length==0) return false;
Arrays.sort(nums);
//求和
int sum=0;
for(int num:nums){
sum+=num;
}
if(sum%2==1) return false;
sum=sum>>1;
return backtrace(nums,nums.length-1,sum);
}
public boolean backtrace(int [] nums,int index,int remain){
if(index<0||remain-nums[index]<0) return false;
//判断是否remain为0
if(remain-nums[index]==0) return true;
//继续递归查找remain
return backtrace(nums,index-1,remain-nums[index])||backtrace(nums,index-1,remain);
}
}