题目 <https://leetcode-cn.com/problems/partition-equal-subset-sum/>
最初想法是两数之和,三数之和的思路
之后的想法是回溯法,直接超时。。。
void sort(int* nums, int numsSize)
{
int left,right,mid,n;
mid = 0;
left = 1;
right = numsSize -1;
if(left>right) return;
while(left<=right)
{
while(left<=right&&nums[mid]<nums[right]) right--;
if(left>right) break;
n = nums[right];
nums[right] = nums[mid];
nums[mid] = n;
mid = right;
right--;
while(left<=right&&nums[mid]>nums[left]) left++;
if(left>right) break;
n = nums[left];
nums[left] = nums[mid];
nums[mid] = n;
mid = left;
left++;
}
sort(nums,mid);
sort(nums+mid+1,numsSize-mid-1);
}
bool canPack(int *nums,int numsSize,int sum,int sum_tmp,int i){
//printf("%d %d\n",sum_tmp,sum);
if(sum_tmp == sum){
return true;
}
else if(sum_tmp > sum){
return false;
}
int j;
for(j=i;j<numsSize && sum_tmp+nums[j] <= sum;j++){
if(canPack(nums,numsSize,sum,sum_tmp+nums[j],j+1) == true){
return true;
}
}
return false;
}
bool canPartition(int* nums, int numsSize){
int i,j;
int sum =0,sum1=0;
for(i=0;i<numsSize;i++){
sum += nums[i];
}
if(sum&1 == 1){
return false;
}
sort(nums,numsSize);
sum>>=1;
return canPack(nums,numsSize,sum,0,0);
}
看了题解,怀疑人生。。。用动态规划解决N数和的另一种思路
bool canPartition(int* nums, int numsSize){
int i,j;
int sum =0;
for(i=0;i<numsSize;i++){
sum += nums[i];
}
if(sum&1 == 1){
return false;
}
sum>>=1;
bool **dp = malloc(sizeof(bool*) * numsSize);//dp[i][j]表示0~i的子集总和是否为j
for(i=0;i<numsSize;i++){
dp[i] = malloc(sizeof(bool) * (sum+1));
}
for(i=0;i<numsSize;i++){
dp[i][0] = true;
}
for(i=0;i<1;i++){
for(j=0;j<=sum;j++){
dp[i][j] = (nums[i] == j);
}
}
for(i=1;i<numsSize;i++){
for(j=1;j<=sum;j++){
if(j-nums[i]>=0){
dp[i][j] = (dp[i-1][j] || dp[i-1][j-nums[i]]);
}else{
dp[i][j] = dp[i-1][j];
}
}
}
bool flag = dp[numsSize-1][sum];
for(i=0;i<numsSize;i++){
free(dp[i]);
}
free(dp);
return flag;
}