题目
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:
Each of the array element will not exceed 100.
The array size will not exceed 200.
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.
动态规划
这题可看作0-1背包问题的变形,将其分为两个相等的数组可以转化为从数组中选择N个元素使其和为原始数组元素和的1/2.
dp[i][j]=True: 表示对于前 i 个元素能得到其和为j.
一个数组中一部分的结果和为sum/2,那么另一部分自然也为sum/2.
状态转移时也可分为选择元素或者不选;
当j-nums[i-1]<0时,不可选,dp[i][j] = dp[i-1][j]
否则dp[i][j] = dp[i - 1][j] | dp[i - 1][j-nums[i-1]]
class Solution(object):
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
ssum = 0
for num in nums:
ssum += num
if (ssum%2) == 1:
return False
ssum =ssum // 2
dp = [[False for j in range(ssum+1)] for i in range(len(nums)+1)]
for i in range(len(nums)+1):
dp[i][0] = True
for i in range(1,len(nums)+1):
for j in range(1,ssum+1):
if j-nums[i-1]<0:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = dp[i - 1][j] | dp[i - 1][j-nums[i-1]]
return dp[len(nums)][ssum]
状态压缩
dp[i][j] = dp[i-1][j]
dp[i][j] = dp[i - 1][j] | dp[i - 1][j-nums[i-1]]
从这两个状态转移方程中可以看出dp[i][j]都是通过上一行结果而来,与本行前面的数据无关,所以可以将二维 dp 数组压缩为一维,节约空间复杂度。
class Solution(object):
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
ssum = 0
for num in nums:
ssum += num
if (ssum%2) == 1:
return False
ssum =ssum // 2
dp = [False for j in range(ssum+1)]
dp[0] = True
for i in range(len(nums)):
for j in range(ssum,-1,-1):
if j-nums[i]<0:
dp[j] = dp[j]
else:
dp[j] = dp[j] | dp[j-nums[i]]
return dp[ssum]