题目描述

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

题解

由题可知,数组nums非空,所以分割后的两个子集也必然非空,由于都是正整数,所以nums中元素之和必然为偶数。

这道题是典型的 01 背包问题,假设$dp[i][j]$表示nums中前$i$个元素是否包含和为$j$的子集,那么:

  1. nums[i] = j的时候,dp[i][j] = true
  2. nums[i] > j的时候,dp[i][j] = dp[i - 1][j]
  3. nums[i] < j的时候,dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]
 1#include <vector>
 2#include <numeric>
 3
 4class Solution {
 5public:
 6    bool canPartition(const std::vector<int>& nums) {
 7        int size = nums.size();
 8        int sum = std::accumulate(nums.begin(), nums.end(), 0);
 9        if (size == 1 || (sum & 1) == 1) return false;
10        int target = sum / 2;
11        std::vector<std::vector<bool>> dp(size + 1, std::vector<bool>(target + 1));
12        for (int i = 1; i <= size; ++i) {
13            for (int j = 1; j <= target; ++j) {
14                int num = nums[i - 1];
15                if (num == j) dp[i][j] = true;
16                else if (num > j) dp[i][j] = dp[i - 1][j];
17                else dp[i][j] = dp[i - 1][j] | dp[i - 1][j - num];
18            }
19        }
20        return dp[size][target];
21    }
22};