题目描述:给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
- 每个数组中的元素不会超过 100
- 数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5] 输出: true 解释: 数组可以分割成 [1, 5, 5] 和 [11].示例 2:
输入: [1, 2, 3, 5] 输出: false 解释: 数组不能分割成两个元素和相等的子集.
解法1。这是个典型的背包问题,能不能找到若干各元素使其和等于sum/2(sum必须是可均分的,不然返回False)。
class Solution(object):
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
if not nums:
return False
summ = sum(nums)
if summ & 1:
return False
memo = [[-1 for _ in range(summ//2+1)] for _ in range(len(nums))]
return self.helper(nums, 0, summ//2, memo)
def helper(self, nums, index, summ, memo):
if summ == 0:
return True
if index >= len(nums) or summ < 0:
return False
if memo[index][summ] != -1:
return memo[index][summ] == 1
if self.helper(nums, index+1, summ, memo) or self.helper(nums, index+1, summ-nums[index], memo):
memo[index][summ] = 1
else:
memo[index][summ] = 0
return memo[index][summ] == 1
解法2。改写成DP,自底向上
class Solution(object):
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
if not nums:
return False
summ = sum(nums)
if summ & 1:
return False
memo = [False for _ in range(summ//2+1)]
c = summ//2
for i in range(c+1):
memo[i] = True if nums[0] == i else False
for i in range(1, len(nums)):
j=c
while j >= nums[i]:
memo[j] = memo[j] or memo[j-nums[i]]
j -= 1
return memo[-1]