LeetCode 416. Partition Equal Subset Sum

简介: 给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

v2-ff43a8b37ce618e4c1d9cc333e279bd8_1440w.jpg

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:

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.


描述



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


注意:

每个数组中的元素不会超过 100

数组的大小不会超过 200


示例 1:

输入: [1, 5, 11, 5]

输出: true

解释: 数组可以分割成 [1, 5, 5] 和 [11].


示例 2:

输入: [1, 2, 3, 5]

输出: false

解释: 数组不能分割成两个元素和相等的子集.


来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/partition-equal-subset-sum

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路



  • 这道题属于背包问题。
  • 给定一个数组,把数组中的数分成两组,使得这两组数组的和相等,等价于:在整个数组中,每个数只可以使用一次,找这样一些数,使得这些数的和为整个数组和的一半。即备选集合为数组,包的大小为数组和的一半。
  • 首先一定不能构成两个和相等的情况可以直接排除,对于一个数组 num,我们记 num 的两个子数组的和为 x,有 x + x = sum(num),所以要求 num 的和一定是偶数,那么如果整个 num 的和是奇数,我们直接返回 False;子数组的和为 x,那么数组 num 的最大值一定小于等于 x,如果最大值大于 x(即 num 和的一半),我们直接返回 False;
  • 我们对数组从小到大排序,动态规划,状态:dp[i][j] 表示是否可以使用 num 的前 i(索引,包括 i) 个数,使其和为 j,
  • 转移方程,对于 dp[i][j],我们已经知道了 dp[i-1] 的所有情况,如果 dp[i-1][j] 为 true,那么我们可以不使用第 i 个数就达到和为 j,如果dp[i-1][j] 为 False,那么我们检查 dp[i-1][j-num[i]] 是否为 true,表示我们使用第 i 个数 num[i],如果 前 i - 1 个数可以构成 j-nums[i] 的话,我们就可以使用前 i 个数使其和为 j。
  • 转移方程为:dp[i][j] = dp[i - 1][j] if dp[i - 1][j] else dp[i - 1][j - nums[i]]
  • 可以参考这个视频


# -*- coding: utf-8 -*-
# @Author:             何睿
# @Create Date:        2019-10-26 09:30:29
# @Last Modified by:   何睿
# @Last Modified time: 2019-10-26 10:18:19
from typing import List
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        sum_nums = sum(nums)
        if sum_nums & 1 or max(nums) > (sum_nums >> 1):
            return
        half_sum = sum_nums >> 1
        nums.sort(reverse=True)
        dp = [[False] * (half_sum + 1) for _ in range(2)]
        dp[0][0] = True
        dp[0][nums[0]] = True
        for i in range(1, len(nums)):
            idx = i % 2
            for j in range(nums[i]):
                dp[idx][j] = dp[idx - 1][j]
            for j in range(nums[i], half_sum + 1):
                dp[idx][j] = dp[idx - 1][j] if dp[idx - 1][j] else dp[idx - 1][j - nums[i]]
            if dp[idx][-1]:
                return True
        return dp[-1][-1]

源代码文件在 这里


目录
相关文章
|
算法
【LeetCode力扣】75 快速排序的子过程partition(荷兰国旗问题)
【LeetCode力扣】75 快速排序的子过程partition(荷兰国旗问题)
78 1
LeetCode 404. Sum of Left Leaves
计算给定二叉树的所有左叶子之和。
81 0
LeetCode 404. Sum of Left Leaves
LeetCode 86. Partition List
给定链表和值x,对其进行分区,使得小于x的所有节点都在大于或等于x的节点之前. 您应该保留两个分区中每个分区中节点的原始相对顺序.
76 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-Medium 416. Partition Equal Subset Sum
Leetcode-Medium 416. Partition Equal Subset Sum
120 0
LeetCode之Sum of Left Leaves
LeetCode之Sum of Left Leaves
95 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), .
964 0