Leetcode-Medium 416. Partition Equal Subset Sum

简介: Leetcode-Medium 416. Partition Equal Subset Sum

题目描述


给定仅包含正整数的非空数组,查找是否可以将数组划分为两个子集,使得两个子集中的元素总和相等。


例子1:

Input: [1, 5, 11, 5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].


例子2:

Input: [1, 2, 3, 5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.


思路


如果两个子集中的元素和相等,那么我们至少可以挖掘两个信息:

  • 如果数组为空,那么应该返回False
  • 如果数组元素相加的和为奇数时,应该范围False。
    因为两个相等的数相加必为偶数(full_sum=target+target=2*target=2*target)
    target=sum(nums)//2=sum(nums)>>1(右移一位相当于整除)


思路1 :找出所有可能子集的和,判断 target是否出现在possible_sums

思路2:动态规划:[LeetCode] Partition Equal Subset Sum 相同子集和分割


定义一个一维的dp数组,其中dp[i]表示原数组是否可以取出若干个数字,其和为i。那么我们最后只需要返回dp[target]就行了。初始化dp[0]为true,由于题目中限制了所有数字为正数,那么就不用担心会出现和为0或者负数的情况。关键问题就是要找出状态转移方程了,我们需要遍历原数组中的数字,对于遍历到的每个数字nums[i],需要更新dp数组,我们的最终目标是想知道dp[target]的boolean值,就要想办法用数组中的数字去凑出target,因为都是正数,所以只会越加越大,那么加上nums[i]就有可能会组成区间 [nums[i], target] 中的某个值,那么对于这个区间中的任意一个数字j,如果 dp[j - nums[i]] 为true的话,说明现在已经可以组成 j-nums[i] 这个数字了,再加上nums[i],就可以组成数字j了,那么dp[j]就一定为true。如果之前dp[j]已经为true了,当然还要保持true,所以还要‘或’上自身,于是状态转移方程如下:

dp[j] = dp[j] || dp[j - nums[i]] (nums[i] <= j <= target)

有了状态转移方程,那么我们就可以写出代码了,这里需要特别注意的是,第二个for循环一定要从target遍历到nums[i],而不能反过来,想想为什么呢?因为如果我们从nums[i]遍历到target的话,假如nums[i]=1的话,那么[1, target]中所有的dp值都是true,因为dp[0]是true,dp[1]会或上dp[0],为true,dp[2]会或上dp[1],为true,依此类推,完全使我们的dp数组失效了


代码实现


思路1

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        if sum(nums) and not sum(nums)%2:
            possible_sums={0}
            for num in nums:
                possible_sums.update({(num+v) for v in possible_sums})
                if sum(nums)>>1 in possible_sums:
                    return True
        return False


思路2

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        sums=sum(nums)
        target=sums>>1
        if not sums or sums%2:
            return False
        dp=[False]*(target+1)
        dp[0]=True
        for num in nums:
            for i in range(target,num-1,-1):
                dp[i]=dp[i] or dp[i-num]
        return dp[target]


相关文章
|
算法
【LeetCode力扣】75 快速排序的子过程partition(荷兰国旗问题)
【LeetCode力扣】75 快速排序的子过程partition(荷兰国旗问题)
85 1
Leetcode 368. Largest Divisible Subset思路及详解
这里有个很简单的数学性质,就是整除的传递性,如果a%b==0 且 b%c == 0,那么a%c == 0,说白了如果c是b的因子,b又是a的因子,那么c肯定是a的因子。这样我们就可以在数组中找出很多整除链(a->b->c->d,其中b是a的因子,c是b的因子,d是c的因子),这样的链条就满足两两整除的条件,题目就变成了求最长的链条。 先上代码,然后我再解释下我的代码。
56 0
|
索引
LeetCode 416. Partition Equal Subset Sum
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
112 0
LeetCode 416. Partition Equal Subset Sum
LeetCode 404. Sum of Left Leaves
计算给定二叉树的所有左叶子之和。
90 0
LeetCode 404. Sum of Left Leaves
LeetCode 86. Partition List
给定链表和值x,对其进行分区,使得小于x的所有节点都在大于或等于x的节点之前. 您应该保留两个分区中每个分区中节点的原始相对顺序.
86 0
LeetCode 86. Partition List
|
人工智能 索引
LeetCode 1013. 将数组分成和相等的三个部分 Partition Array Into Three Parts With Equal Sum
LeetCode 1013. 将数组分成和相等的三个部分 Partition Array Into Three Parts With Equal Sum
LeetCode之Sum of Left Leaves
LeetCode之Sum of Left Leaves
103 0
LeetCode 561:数组拆分 I Array Partition I
文章全部来自公众号:爱写bug 算法是一个程序的灵魂。Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1, b1), (a2, b2), .
968 0
|
人工智能 BI 文件存储
LeetCode 561 Array Partition I(数组划分)
版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net/NoMasp/article/details/71244260 ...
1283 0