416. 分割等和子集⭐

5 阅读1分钟

416. 分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

开始我想的是用一个类似于贪心算法的办法,算出相加和除以2为sum以后,只需要找出一些数字能让他的结果等于sum就可以证明,但是让sum从最大值开始减去,如果能为0就可以.代码如下

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        if not nums:
            return False
        s=sum(nums)
        if s%2!=0:
            return False
        summ=s/2
        nums.sort(reverse=True)
        i=0
        while i!=len(nums):
            if nums[i]<=summ:
                summ=summ-nums[i]
            if summ==0:
                return True
            i=i+1
        return False

但是显然存在反例 比如 6 5 4 3 3 3 用这个办法就无法得到结果.

那么我们想到另一个办法,因为他只需要返回true或者false,只需要判断存不存在就可以,可以列出所有可能存在的值,为了减少运算超过sum的不管,只要存在sum就说明可以是true.这里如果是我,我会运用hash表的办法,但是并不是很好搞. 正确答案如下

def canPartition(self, nums: List[int]) -> bool:
    total = sum(nums)
    if total % 2 != 0:
        return False
    target = total // 2
    dp = [False] * (target + 1)
    dp[0] = True
    for num in nums:
        for j in range(target, num - 1, -1):
            dp[j] = dp[j] or dp[j - num]
    return dp[target]

用了一个类似于反向的办法,跟点星星一样,如果存在就点亮,对于任意一个j来说,如果它本身就是存在过的,或者它减去num的那个值存在过,那么这个j就应该存在.