给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
参考:
python
# 0416.分割等和子集
class Solution:
def canPartition(self, nums: [int]) -> bool:
"""
动态规划, 时间O(n^2), 空间O(n)
01背包相对于本题,主要要理解,题目中物品是nums[i],
重量是nums[i]i,价值也是nums[i],背包体积是sum/2
01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。
所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
:param nums:
:return:
"""
target = sum(nums)
if target % 2 == 1: return False
target //= 2
dp = [0] * 10001
for i in range(len(nums)):
for j in range(target, nums[i]-1, -1):
dp[j] = max(dp[j], dp[j-nums[i]]+nums[i])
return target == dp[target]
golang
package dynamicPrograming
// 动态规划
func canPartition(nums []int) bool {
var sum int
for _, v := range nums {
sum += v
}
// check odd || even
if sum % 2 == 1 || len(nums) < 1 {
return false
}
var target int = sum / 2
dp := make([]bool, target+1)
dp[0] = true
for i := 0; i < len(nums); i++ {
v := nums[i]
for j := target; j >= v; j-- {
dp[j] = dp[j] || dp[j-v]
}
}
return dp[target]
}