📜  门| GATE-CS-2017(套装2)|第 54 题(1)

📅  最后修改于: 2023-12-03 14:58:32.209000             🧑  作者: Mango

题目描述

给定一组整数,编写一个程序来判断这些整数是否可以按以下方式分成两组:

  • 第一组的所有元素的和等于第二组的所有元素的和。
  • 每个元素要么属于第一组,要么属于第二组。
  • 您可以假设输入组的数量不超过 20,且每个元素都不超过 100。
函数签名
def can_partition(nums: List[int]) -> bool:
示例
assert can_partition([1, 5, 11, 5]) == True
assert can_partition([1, 2, 3, 5]) == False
解题思路

这是一道0/1背包的问题,可以使用动态规划来解决。

首先分析,对于一个给定的集合$S$,如果 $S$ 的和是奇数,那么它就肯定不能被分成两个和相等的集合。

接着,我们设计一个0/1背包问题。从集合 $S$ 中选择一些数,放到集合$A$ 中,剩下的放到集合 $B$ 中,使两个集合的和相等。

对于这个0/1背包问题,我们需要考虑的是,每个元素选或不选两种情况。当总和等于 $sum/2$ 时,我们找到了一组合法解,返回True即可。

代码实现
from typing import List

def can_partition(nums: List[int]) -> bool:
    n = len(nums)
    if n == 0:
        return True
        
    if sum(nums) % 2 != 0:
        return False

    C = sum(nums) // 2
    dp = [False] * (C+1)
    dp[0] = True

    for i in range(0, n):
        for j in range(C, nums[i]-1, -1):
            dp[j] = dp[j] or dp[j-nums[i]]

    return dp[C]