力扣算法题-416.分割等和子集 C语言实现

题目

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意:
每个数组中的元素不会超过 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);
}

猜你喜欢

转载自blog.csdn.net/MDJ_D2T/article/details/109018159