给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 注意: 每个数组中的元素不会超过 100
数组的大小不会超过 200 来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
bool canPartition(int* nums, int numsSize){
int sum = 0;
for(int i = 0; i < numsSize; i++)
{
sum += nums[i];
}
if((sum & 1) == 1)
{
return false;
}
int target = sum / 2;
bool dp[numsSize][target+1];
memset(dp, false, sizeof(dp));
dp[0][0] = true;
for(int i = 0; i < numsSize && nums[i] <= target; i++)
{
dp[0][nums[0]] = true;
}
for(int i = 1; i < numsSize; i++)
{
for(int j = 0; j <= target; j++)
{
dp[i][j] = dp[i-1][j];
if(nums[i] <= j)
{
dp[i][j] = dp[i-1][j] || dp[i-1][j - nums[i]];
}
}
if(dp[i][target])
{
return true;
}
}
return false;
}
思路:动态规划
首先将这个数组分割成两个子集,使得两个子集的元素和相等,那么言外之意就是这个数组的和为偶数才可以使得两个子集元素和相等。
那么定义一个状态数组,dp[i][j]:表示在0~i的下标中,能否找到子集和刚好为j的子集。
状态转移方程:
对于nums[i], dp[i][j]就有一个取舍问题,假如nums[i] > j, 那么这肯定是放不下了,就不拿,dp[i][j = dp[i-1][j]
num[i] == j, 表明0~i的下标中,能找到子集和刚好为j的子集, dp[i][j == true;
假如nums[i] < j, 那就需要看看在0~i-1中,有无子集和刚好为j-nums[i]的子集,dp[i][j] = dp[i-1][j-nums[i]]