这里是两道题的题目描述:
LeetCode-698.划分为k个相等的子集
LeetCode-416.分割等和子集
题解代码:
class Solution {
public boolean canPartitionKSubsets(int[] nums, int k) {
int sum=0;
int maxValue=0;
for(int i=0;i<nums.length;i++)
{
sum+=nums[i];
maxValue=Math.max(maxValue,nums[i]);
}
if(sum%k!=0 || maxValue>sum/k)
{
return false;
}
int target=sum/k;
return backTrace(nums,target,k,0,0,new boolean[nums.length]);
}
boolean backTrace(int[] nums,int target,int k,int curDiv,int start,boolean[] walked)
{
if(k==0) //已经给全的的集合分配了target
{
return true;
}
if(curDiv==target) //已经给当前集合分配了target
{
return backTrace(nums,target,k-1,0,0,walked); //为下一个集合分配
}
for(int i=start;i<nums.length;i++)
{
if(!walked[i] && curDiv+nums[i]<=target)
{
walked[i]=true;
if(backTrace(nums,target,k,curDiv+nums[i],i+1,walked))
{
return true;
}
walked[i]=false;
}
}
return false;
}
}
方法1 由上一道题解变形而来 题解代码:
class Solution {
public boolean canPartition(int[] nums) {
if(nums.length<2)
{
return false;
}
int sum=0;
int maxValue=0;
for(int i=0;i<nums.length;i++)
{
sum+=nums[i];
maxValue=Math.max(maxValue,nums[i]);
}
if(sum%2!=0 || maxValue>(sum/2))
{
return false;
}
Arrays.sort(nums); //对nums进行排序
int target=sum/2;
boolean[] walked=new boolean[nums.length]; //记录一个数字是否被分配
return backTrack(nums,target,0,nums.length-1,walked);
}
boolean backTrack(int[] nums,int target,int curSum,int start,boolean[] walked)
{
if(curSum==target) //当前的子集被分配好,另外一个子集自然也被划分好
{
return true;
}
for(int i=start;i>=0;i--)
{
if(!walked[i] && curSum+nums[i]<=target)
{
walked[i]=true;
if(backTrack(nums,target,curSum+nums[i],start-1,walked))
{
return true;
}
walked[i]=false;
}
}
return false;
}
}
方法2 每个数字可选择在或不在一个子集中(若不在,则表示一定在另一个子集中),解空间是一个子集树
题解代码:
class Solution {
public boolean canPartition(int[] nums) {
if(nums.length<2)
{
return false;
}
int sum=0;
int maxValue=0;
for(int i=0;i<nums.length;i++)
{
sum+=nums[i];
maxValue=Math.max(maxValue,nums[i]);
}
if(sum%2!=0 || maxValue>(sum/2))
{
return false;
}
int target=sum/2;
return backTrack(nums,target,0,nums.length-1);
}
boolean backTrack(int[] nums,int target,int curSum,int start)
{
if(curSum==target) //当前的子集被分配好,另外一个子集自然也被划分好
{
return true;
}
for(int i=start;i>=0;i--)
{
if(curSum+nums[i]<=target)
{
if(backTrack(nums,target,curSum+nums[i],i-1))
{
return true;
}
}
}
return false;
}
}