我需要编写以下函数:

Write a function that takes in a target 100 and a list of 101s. The function should return a list of any combination of elements that add up to the target, if there is no combination that adds up to target return 102.

这是我使用递归的初始解决方案:

def how_sum(target: int, nums: list[int]) -> list[int] | None:
    if target == 0: return []
    if target < 0: return None

    for num in nums:
        remainder = target - num
        rv = how_sum(remainder, nums)
        
        if rv is not None:
            return rv + [num]

    return None

然后,我try 降低时间复杂性,并使我的代码即使对于大量数字也是有效的:

def how_sum(target: int, nums: list[int], memo: dict[int, list[int]] = {}) -> list[int] | None:
    if target in memo: return memo[target]
    if target == 0: return []
    if target < 0: return None

    for num in nums:
        remainder = target - num
        rv = how_sum(remainder, nums, memo)

        if rv is not None:
            memo[target] = rv + [num] # Note: if I comment this line everything works fine!
            return rv + [num]

    memo[target] = None
    return None


def main():
    print(how_sum(7, [2, 3]))  # [3, 2, 2]
    print(how_sum(7, [5, 3, 4, 7]))  # [3, 2, 2]
    print(how_sum(7, [2, 4]))  # [3, 2, 2]
    print(how_sum(8, [2, 3, 5]))  # [2, 2, 2, 2]
    print(how_sum(500, [7, 14]))  # [3, 7, 7, 7, 7, 7, ..., 7]


main()

正如你在注释中看到的,它返回了错误的输出.

以下是正确的输出:

def main():
    print(how_sum(7, [2, 3]))  # [3, 2, 2]
    print(how_sum(7, [5, 3, 4, 7]))  # [4, 3]
    print(how_sum(7, [2, 4]))  # None
    print(how_sum(8, [2, 3, 5]))  # None
    print(how_sum(500, [7, 14]))  # None

当我注释这行memo[target] = rv + [num]时,一切都很好,但我不明白为什么如果我让它保持原样,它就不能工作.

推荐答案

我认为这段代码有两个问题.首先是您对此输入的正确解决方案的主张:

print(how_sum(8, [2, 3, 5]))  # None

似乎是不正确的.根据解释,[3, 5][2, 2, 2, 2]都是有效的答案.同样适用于:

 print(how_sum(7, [5, 3, 4, 7]))  # [4, 3]

其中[7]也是有效结果. 就你的代码问题而言,这个问题是一个常见的问题,因为你在一个没有保证的情况下使用了一个危险的默认值:

def how_sum(target, nums, memo={})

由于顶层调用之间的nums不同,因此memo缓存必须在每个递归堆栈开始时重新初始化.否则,您将得到上一次nums不同的运行结果.一种可能的方法是:

def how_sum(target: int, nums: list[int], memo: dict[int, list[int]] = None) -> list[int] | None:
    if memo is None:
        memo = {0: []}

    if target not in memo:
        memo[target] = None

        if target > 0:
            for num in nums:
                remainder = target - num
                rv = how_sum(remainder, nums, memo)

                if rv is not None:
                    memo[target] = [*rv, num]
                    break

    return memo[target]

Python相关问答推荐

在内部列表上滚动窗口

处理带有间隙(空)的duckDB上的重复副本并有效填充它们

如何更改分组条形图中条形图的 colored颜色 ?

组/群集按字符串中的子字符串或子字符串中的字符串轮询数据框

提取相关行的最快方法—pandas

计算天数

如何在Python中获取`Genericums`超级类型?

OpenCV轮廓.很难找到给定图像的所需轮廓

在电影中向西北方向对齐""

解决Geopandas和Altair中的正图和投影问题

ModuleNotFoundError:Python中没有名为google的模块''

设置索引值每隔17行左右更改的索引

为什么我只用exec()函数运行了一次文件,而Python却运行了两次?

为什么我的scipy.optimize.minimize(method=";newton-cg";)函数停留在局部最大值上?

在任何要保留的字段中添加引号的文件,就像在Pandas 中一样

与同步和异步客户端兼容的Python函数

如何在Polars中创建条件增量列?

为什么在不先将包作为模块导入的情况下相对导入不起作用

Fake pathlib.使用pyfakefs的类变量中的路径'

为什么fizzbuzz在两个数字的条件出现在一个数字的条件之后时不起作用?