一、题目【原题链接】
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Example 1:
Input: [1, 5, 11, 5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.
二、分析
数组能够划分,则该数组总和sum%2 != 0,另 s = sum / 2
该问题能简化为0-1背包问题,另dp[i][j](布尔数组)为 在数组前i个数字中选择 某几个数字,是否能够使这几个数字总和等于 j,当i=array.length,j=s时,就能得到答案。
对于nums[i],dp[i][j] = dp[i-1][j](不选择nums[i]) || dp[i][j-nums[i-1]](选择nums[i]),由此,能得以下源代码
三、源代码
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
//求和并判断该和是否能整除2
for(int i = 0; i < nums.size(); i ++)
sum += nums[i];
if(sum % 2 != 0)
return false;
sum = sum /2;
//初始化:
bool dp[nums.size() + 1][sum + 1];
dp[0][0] = true;
//没有数选择,所以为false
for(int i = 1; i < sum +1; i ++)
dp[0][i] = false;
//对于所有数可以都不选择,所以为true,注意不能单纯从题目来理解,而是从dp意义来理解
for(int i =1; i < nums.size() + 1; i ++)
dp[i][0] = true;
//递推式,之前已经初始化好了第一列和第一行
for(int i = 1; i < nums.size() + 1; i ++)
{
for(int j = 1; j < sum + 1; j ++)
{
dp[i][j] = dp[i-1][j];
if(j >= nums[i - 1])
dp[i][j] = (dp[i-1][j] || dp[i-1][j-nums[i-1]]);
}
}
return dp[nums.size()][sum];
}
};