Description:
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
Example 1:
Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.
题目中文描述:
解题思路:
注意题目中的限制:
题目中的限制条件可以帮助我们判断设计的算法的可行性和有效性。
每个数字的最大值决定了我们背包的容量,进而决定了我们算法的复杂度。
在LeetCode中“Time Limit Exceeded”,不能通过。
class Solution:
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
num_sum = 0
for i in range(len(nums)):
num_sum += nums[i]
if num_sum % 2 != 0:
return False
return self.tryPartition(nums, len(nums)-1, num_sum/2)
def tryPartition(self, nums, index, _sum):
if _sum == 0:
return True
if _sum < 0 or index < 0:
return False
return self.tryPartition(nums, index-1, _sum) or \
self.tryPartition(nums, index-1, _sum-nums[index])
solution = Solution()
# test1
# nums = [1, 5, 11, 5]
# test2
nums = [1, 2, 3, 5]
print(solution.canPartition(nums))
在LeetCode中可以AC。
class Solution:
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
num_sum = 0
for i in range(len(nums)):
num_sum += nums[i]
if num_sum % 2 != 0:
return False
# memo[i][c]表示使用索引为[0...i]的这些元素是否可以完全填充一个容量为c的背包
# -1表示为未计算;0表示不可以填充;1表示可以填充
memo = [[-1] * (int(num_sum / 2) + 1) for _ in range(len(nums))]
def tryPartition(nums, index, _sum):
if _sum == 0:
return True
if _sum < 0 or index < 0:
return False
if memo[index][_sum] != -1:
return memo[index][_sum] == 1
memo[index][_sum] = 1 if (tryPartition(nums, index - 1, _sum) or tryPartition(nums, index - 1, _sum - nums[index])) else 0
return memo[index][_sum] == 1
return tryPartition(nums, len(nums)-1, int(num_sum / 2))
solution = Solution()
# test1
# nums = [1, 5, 11, 5]
# test2
nums = [1, 2, 3, 5]
print(solution.canPartition(nums))
使用优化后的动态规划解法,详细介绍文章《动态规划学习-【0-1背包问题的优化和变种】》
已经AC的代码:
class Solution:
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
num_sum = 0
for i in range(len(nums)):
num_sum += nums[i]
if num_sum % 2 != 0:
return False
n = len(nums)
C = int(num_sum / 2)
memo = [False] * (C + 1)
for i in range(C + 1):
memo[i] = (nums[0] == i)
for i in range(1, n):
for j in range(C, nums[i], -1):
memo[j] = memo[j] or memo[j - nums[i]]
return memo[C]
solution = Solution()
# test1
# nums = [1, 5, 11, 5]
# test2
# nums = [1, 2, 3, 5]
# test3
nums = [1, 2, 5]
print(solution.canPartition(nums))