问题描述
力扣 416. 分割等和子集要求判断一个非空数组是否可以分成两个子集,使得两个子集的元素和相等。例如,给定数组 [1, 5, 11, 5],可以分割为 [1, 5, 5] 和 [11],两个子集的和均为 11。
解题思路
动态规划是解决此问题的有效方法。关键在于将问题转化为背包问题:是否能从数组中选出若干元素,使其和等于数组总和的一半。若总和为奇数,直接返回 false;否则,问题转化为 0-1 背包问题。
动态规划实现
定义一个布尔型动态规划数组 dp,其中 dp[j] 表示是否存在子集的和为 j。初始化时,dp[0] 为 true,其余为 false。遍历数组中的每个元素,更新 dp 数组。
def canPartition(nums):
total_sum = sum(nums)
if total_sum % 2 != 0:
return False
target = total_sum // 2
dp = [False] * (target + 1)
dp[0] = True
for num in nums:
for j in range(target, num - 1, -1):
dp[j] = dp[j] or dp[j - num]
return dp[target]
复杂度分析
- 时间复杂度:O(n * target),其中
n是数组长度,target是数组总和的一半。 - 空间复杂度:O(target),动态规划数组的大小为
target + 1。
示例分析
以 nums = [1, 5, 11, 5] 为例:
- 总和为 22,目标
target为 11。 - 初始化
dp为[True, False, ..., False](长度为 12)。 - 遍历
nums更新dp:- 处理
1后,dp[1]变为True。 - 处理
5后,dp[5]和dp[6]变为True。 - 处理
11后,dp[11]变为True。
- 处理
- 最终
dp[11]为True,返回true。
注意事项
- 数组总和必须为偶数才能分割。
- 动态规划数组需从后往前更新,避免重复计算。
- 当
target较大时,需注意空间优化。
180

被折叠的 条评论
为什么被折叠?



