题目简介:
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
- 每个数组中的元素不会超过 100
- 数组的大小不会超过 200
示例 1:
1 | 输入: [1, 5, 11, 5] |
示例 2:
1 | 输入: [1, 2, 3, 5] |
思路:
我们记所有元素的和为sum
,由于sum
为奇数时,无法分成两个相同的和,所以直接返回false
。
当sum
为偶数时,我们需要知道是否能找到一种选数字的方案,使其和等于sum / 2
,则剩余的数字和也为sum / 2
。
这时我们可以使用动态规划,dp[i][j]
代表在nums[0...i]
中,是否可以选出一种方案(可以不选数字),使其和为j
。
我们先考虑边界情况:
dp[i][0] = true
(不选数字,和就为0)dp[0][nums[0]] = true
由于数组中都为正数,所以可以分为两种情况讨论:
- 当
j - nums[i] < 0
时,说明之前的i - 1
个数存在和为负数的方案,由于不可能存在该情况,所以不能选这个数字,则dp[i][j] = dp[i - 1][j]
。 - 当
j - nums[i] >= 0
时,选不选这个数字都可以,则dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]
。(注意都是i - 1
,当前i - 1
个数字可以选择出j - nums[i]
的和时,加上nums[i]
,则和为j
)
最后返回dp[nums.size() - 1][sum]
即可。
tip:
- 我们还需要找出数组中最大的数字,若该数字大于
sum / 2
,则必不可能存在方案,直接返回false
即可。
代码如下:
1 | class Solution { |