题解:分割等和子集

动态规划 dp

根据数组的长度 num.size() 判断数组是否可以被划分。如果 n%2!=0,则不可能将数组分割成元素和相等的两个子集,因此直接返回 false。

计算整个数组的元素和 sum 以及最大元素maxNum。如果 sum 是奇数,则不可能将数组分割成元素和相等的两个子集,因此直接返回false。如果 sum 是偶数,则令 target= sum/2,如果 数组num中maxNum>target,直接返回false。

之后我们创建一个二维数组

vector<vector<int>dp(num.size(),vector<int>(target,0));
Dp[i][j] 

i表示 从数组num[0~i] 中选取任意个元素 j表示和,

如果相加存在等于j

则 dp[i][j]=1;

其中有两个边界

1.如果不选任何的正整数,则和可以为0:则dp[i][0]=1(0<i<num.size());

2.当i==0的时候只有num[0]可以选取 则dp[0][num[0]=1;

对于 i>0i>0 且 j>0j>0 的情况,如何确定 \textit{dp}[i][j]dp[i][j] 的值?需要分别考虑以下两种情况。

如果j>=num[i] 则当前数字num[i]可以选取,也可以不选取 只要一种情况为true 则都可以

如果j<num[i],则无法选取

formula

最终返回

dp[sum.size()-1][target]

为答案

   `class Solution
   {  
       bool canPartiton(vector<int>&nums)
       {
           sort(nums.begin(),nums.end());
           int total=0,len=nums.size();
           if(len<2||(len==2&&num[0]!=nums[1]))
               return false;  
           for(int i=0;i<len;i++)total+=nums[i];
           if(total%2!=0) return false;
           int half—total/2;
           if(nums[len-1]>half) return false;
           vector<vector<int>>dp(len,vector<int>(half+1,0));
           for(int i=1;i<len;i++) dp[i][0]=1;
           dp[0][nums[0]]=1;
           for(int i=1;i<len;i++)
           {
               for(int j=1;j<half+1;j++)
               {
                   if(j>=nums[i])
                       dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i]];
                   else
                       dp[i][j]=dp[i-1][j];
               }
           }
               return dp[len-1][half];
       }
   };