题目
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
示例 2:
输入: [1, 2, 3, 5]
输出: false
解释: 数组不能分割成两个元素和相等的子集.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
思路
1、动态规划二维;数组a[i][j] 表示0-i范围内的数可否有和为j;i [0,数据长度),j [0, 数组和/2];
图解详见:动态规划二维
2、动态规划一维;数组a[i] 表示是否会存在和为i, i [0, 数组和/2] ;
图解详见:动态规划一维
3、递归DFS;(这个方法提交超出了时间限制,仅提供个思路)
程序
动态规划二维
bool canPartition(int* nums, int numsSize){
int i,j,max = 0,total=0,sum = 0;
for(i=0;i<numsSize;i++){
total+=nums[i];
if(nums[i] > max){
max = nums[i];
}
}
if(total%2 != 0 || numsSize < 2 || max > total/2){
return false;
}else{
sum = total/2;
int** a=(int**)malloc(sizeof(int*)*numsSize);
a[0] = (int*)malloc(sizeof(int)*(sum+1));
memset(a[0],0,sizeof(int)*(sum+1));
a[0][nums[0]] = 1;
for(i=1;i<numsSize;i++){
a[i]=(int*)malloc(sizeof(int)*(sum+1));
memset(a[i],0,sizeof(int)*(sum+1));
a[i][0] = 1;
for(j=1;j<sum+1;j++){
if(j>=nums[i]){
a[i][j] = a[i-1][j] | a[i-1][j-nums[i]];
}else{
a[i][j] = a[i-1][j];
}
}
}
return a[numsSize-1][sum];
}
return false;
}
动态规划一维
bool canPartition(int* nums, int numsSize){
int i,j,ibgn=0,max = 0,total=0,sum = 0;
for(i=0;i<numsSize;i++){
total+=nums[i];
if(nums[i] > max){
max = nums[i];
}
}
if(total%2 != 0 || numsSize < 2 || max > total/2){
return false;
}else{
sum = total/2;
short* a=(short*)malloc(sizeof(short)*(sum+1));
memset(a, 0, sizeof(short)*(sum+1));
a[0] = 1;
for(i=0;i<numsSize;i++){
if(ibgn+nums[i] > sum){
ibgn = sum - nums[i];
}
for(j=ibgn;j>=0;j--){
a[j+nums[i]] |= a[j];
}
ibgn+=nums[i];
if(a[sum]){
return true;
}
}
}
return false;
}
递归DFS
int cmp(const void *a, const void *b){
return *(int*)b - *(int*)a;
}
bool dfs(int* nums, int numsSize, int ibgn, int idiff)
{
for (int j = ibgn; j < numsSize; ++j) {
if (idiff == nums[j]) {
return true;
} else if (idiff > nums[j]) {
if (dfs(nums, numsSize, j + 1, idiff - nums[j])) {
return true;
}
}
}
return false;
}
bool canPartition(int* nums, int numsSize){
int sum = 0;
qsort(nums, numsSize, sizeof(int), cmp);
for (int i = 0; i < numsSize; ++i) {
sum += nums[i];
}
if (numsSize < 2 || sum%2 != 0 || sum/2 < nums[0]) {
return false;
}
return dfs(nums, numsSize, 0, sum/2);
}