最后更新于
最后更新于
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:
示例 2:
如果数组中的数字之和是奇数, 肯定找不到两个子集的元素和相等. 偶数才能划分成两个和相等的子集.
现在问题就转化成了能否找到一个子序列的和为sum(raw_list) // 2
. 这种在原列表中找出一个子集, 使得子集的和为一个指定数字的问题, 一般转换为背包问题来解决.
以背包问题的思路考虑, 物品是数组中的每一个数, 背包容量就是原数组之和的一般. 由于数组中每个元素只能用1次, 因此这是一个01背包的问题.
每个元素对应的重量就是自身的数值大小, 价值也可以为自身的数值大小. 问题就变成状态矩阵dp[-1][-1]
的值是否等于原数组之和的一般. 如果等于说明可以找到一组元素组成子序列, 其和等于原数组之和的一半.
使用滚动数组的代码如下:
本题中, 我们不关心装满背包后的价值, 只关心能否恰好装满. 因此状态矩阵的定义可以修改为: dp[i][j]
代表使用前i个物品, 能否恰好装满容量为j的背包. 因此dp中的值为True/False
. 对应的状态转移公式也变为:
即考虑当前物品i装与不装入背包两种情况, 只要有一种情况符合就可以.
初始化全部为False, 除了dp[i][0]要 初始化为True
. 因此恰好装入容量为0的背包, 只需要什么都不装就可以了.
使用滚动数组的代码如下:
上面还是在按照背包问题的传统思路在走. 背包问题的一种扩展就是能否恰好装满指定容量背包的问题. 这个情况在中有说明.