leetcode学习笔记(416分割等和子集)

112 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

来源:力扣(LeetCode)
链接:leetcode.cn/problems/pa…

因为昨天的背包问题不是很理解,所以又在leetcode上找了几道题,再多学习一下

416. 分割等和子集

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

示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

代码

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        n = len(nums)
        if sum(nums) % 2 == 1:
            return False
        target = sum(nums)  // 2
        if max(nums) > target:
            return False
        
        dp = [[False] * (target+1) for _ in range(n)]
        dp[0][nums[0]] = True
        for i in range(1,n):
            dp[i][0] = True
            for j in range(1,target+1):
                if j >= nums[i]:
                    dp[i][j] = dp[i-1][j] | dp[i-1][j-nums[i]]
                else:
                    dp[i][j] = dp[i-1][j]
        return dp[-1][-1]

解析

其实我没懂这个为啥不是动态规划啊,是我学的不扎实啊

具体步骤: 1.首先数列加和为奇数,数列最大值比数列加和一半大的时候提前结束(原因很简单)
2.生成一个矩阵,初始化成False,dp[i][j]表示0-i里面取数加起来能不能等于j。因此矩阵的行数由数列加和一半决定,列数由数列长度决定
3.dp[0][nums[0]],dp[i][0]肯定都可以生成
4.数列0-i可不可以生成j可以又之前的生成与否决定,dp[i-1][j]或dp[i-1][j-nums[i]]有一个为True则dp[i][j]也可以生成
5.把矩阵的值填满后,最后一个位置的值就是数组不能分割成两个元素和相等的子集。