📅  最后修改于: 2023-12-03 14:53:55.706000             🧑  作者: Mango
给定一个非负整数数组 nums,将其划分为两个子集,使得两个子集的元素和相等(即所有元素之和为偶数)。你可以假设数组中元素个数不超过 100,且每个元素不超过 100。
首先,我们可以算出数组的总和 sum
,如果 sum
为奇数,直接返回 FALSE
。
接下来,我们定义 $dp[i][j]$ 为在前 $i$ 个元素中,单元素和不超过 $j$ 的最大子集和。这样,最终的答案即为 $dp[n][sum/2]$。
使用动态规划进行解决,状态转移方程如下:
$dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i-1]]+nums[i-1])$。
class Solution:
def canPartition(self, nums: List[int]) -> bool:
n = len(nums)
if sum(nums) % 2 == 1:
return False
target = sum(nums) // 2
dp = [[False] * (target + 1) for _ in range(n)]
dp[0][0] = True
if nums[0] <= target:
dp[0][nums[0]] = True
for i in range(1, n):
for j in range(target + 1):
dp[i][j] = dp[i - 1][j]
if nums[i] <= j:
dp[i][j] |= dp[i - 1][j - nums[i]]
return dp[n - 1][target]
时间复杂度:$O(n \times m)$
空间复杂度:$O(n \times m)$
其中,$n$ 表示数组的长度,$m$ 表示数组的总和的一半。