📌  相关文章
📜  给定数组中所有和为完美数的所有子集的总和(1)

📅  最后修改于: 2023-12-03 15:11:40.320000             🧑  作者: Mango

题目描述

给定数组 nums,找出所有的子集,使得子集元素之和为完美数(即完全平方数),返回子集元素之和的总和。

示例

输入:nums = [1,2,3]

输出:4

解释:子集 [1,3] 和 [4] 的元素之和是完美数

解法

首先我们需要一个函数来判断一个数是否为完全平方数。这里使用牛顿迭代法来计算平方根,具体过程可以参考 牛顿迭代法详解

def isPerfectSquare(num: int) -> bool:
    if num < 0:
        return False
    if num == 0:
        return True
    x = num
    while x * x > num:
        x = (x + num // x) // 2
    return x * x == num

接着,我们可以使用 DFS(深度优先搜索)来遍历所有的子集。在搜索过程中需要记录下当前子集的元素之和,如果符合完美数的条件,则累加到答案中。具体代码如下:

def subsetSum(nums: List[int], target: int, start: int, path: List[int], res: List[List[int]]) -> None:
    if target == 0 and len(path) > 0:
        res.append(path)
        return
    for i in range(start, len(nums)):
        if nums[i] > target:
            break
        subsetSum(nums, target - nums[i], i + 1, path + [nums[i]], res)

def allSubsets(nums: List[int]) -> List[List[int]]:
    res = []
    subsetSum(nums, sum(nums), 0, [], res)
    return res

def subsetSumPerfect(nums: List[int]) -> int:
    res = 0
    subsets = allSubsets(nums)
    for sub in subsets:
        if isPerfectSquare(sum(sub)):
            res += sum(sub)
    return res
完整代码
from typing import List

def isPerfectSquare(num: int) -> bool:
    if num < 0:
        return False
    if num == 0:
        return True
    x = num
    while x * x > num:
        x = (x + num // x) // 2
    return x * x == num

def subsetSum(nums: List[int], target: int, start: int, path: List[int], res: List[List[int]]) -> None:
    if target == 0 and len(path) > 0:
        res.append(path)
        return
    for i in range(start, len(nums)):
        if nums[i] > target:
            break
        subsetSum(nums, target - nums[i], i + 1, path + [nums[i]], res)

def allSubsets(nums: List[int]) -> List[List[int]]:
    res = []
    subsetSum(nums, sum(nums), 0, [], res)
    return res

def subsetSumPerfect(nums: List[int]) -> int:
    res = 0
    subsets = allSubsets(nums)
    for sub in subsets:
        if isPerfectSquare(sum(sub)):
            res += sum(sub)
    return res
复杂度分析
  • 时间复杂度:$O(2^n)$,其中 $n$ 是数组 nums 的长度。dfs 遍历所有子集的时间复杂度为 $O(2^n)$,每个子集求和的时间复杂度为 $O(n)$。
  • 空间复杂度:$O(2^n)$,除答案集合外,空间复杂度为 $O(n)$,存储递归栈的最大深度。