416. 分割等和子集 Partition Equal Subset Sum

题目 <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;
}

 

上一篇:Leetcode算法刷题笔记-递归与回溯


下一篇:自顶向下语法分析复习总结