【问题标题】:Dynamic programming best sum code in pythonpython中的动态编程最佳求和代码
【发布时间】:2021-11-03 02:52:07
【问题描述】:

我正在尝试通过关注在线视频来学习动态编程。原始视频使用 javascript,我正在尝试使用 python 来实现相同的。但是,我无法在我的 python 实现中找到错误。

问题如下

写一个fn。 bestsum(targetsum, numbers) 接受目标和 一个数字数组作为参数。

fn.应该返回一个包含最短组合的数组 加起来正好是目标和的数字。

如果最短的组合出现平局,您可以返回任意组合 最短的。

javascript实现如下。

const bestSum = (targetSum, numbers, memo={}) => {
    if (targetSum in memo) return memo[targetSum];

    if (targetSum === 0) return [];
    if (targetSum < 0) return null;

    let shortest_com = null;

    for (let num of numbers) {
        const remainder = targetSum - num;
        const remainder_com = bestSum(remainder, numbers, memo);

        if (remainder_com !== null) {
            const combination = [...remainder_com, num];

            if (shortest_com === null || combination.length < shortest_com.length) {
                shortest_com = combination;
            }
        }
    }

    memo[targetSum] = shortest_com
    return shortest_com;
}; 

console.log(bestSum(7, [5, 3, 4, 7]));
console.log(bestSum(8, [2, 3, 5]));
console.log(bestSum(8, [1, 4, 5]));
console.log(bestSum(100, [1, 2, 5, 25]));

我实现的Python代码是

from typing import Any, Dict, List, Optional


def best_sum(target: int, numbers: List[int], memo:Dict[int, Any]={}) -> Optional[List[int]]:
    if target in memo.keys():
        return memo.get(target)

    if target == 0:
        return []

    if target < 0:
        return None

    shortest_combination: Optional[List] = None
    for num in numbers:
        partial = best_sum(target=target - num, numbers=numbers, memo=memo)
        if partial != None:
            print(num)
            partial.append(num)

            if (shortest_combination == None) or (len(partial) < len(shortest_combination)):
                shortest_combination = partial

    memo[target] = shortest_combination
    return shortest_combination


if __name__ == "__main__":
    print(best_sum(target=100, numbers=[1, 2, 5, 25]))

对于测试用例:target=100, numbers=[1, 2, 5, 25]。

Javascript 实现给出了。 [25、25、25、25]

但是 Python 提供了。

[25, 1, 1, 2, 1, 2, 1, 2, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1, 2, 5, 25, 1、2、5、25、1、2、5、25、1、2、5、25、1、2、5、25、1、2、5、25、1、2、5、25]

【问题讨论】:

  • “我无法定位错误” - 你怎么知道有错误?实际和预期的输出是多少?
  • 此行为是this post 中解释的标准 Python 列表行为的更迂回版本。例如,每次您在第一次之后调用 best_sum(0),返回的是对 memo[0] 中列表的引用,您将其附加到该列表,以便所有未来调用在调用 best_sum(0) 时看到更新的值),因此 best_sum(x) 每次调用时都会变长。

标签: python-3.x dynamic-programming


【解决方案1】:

问题出在这个sn-p:

if partial != None:
    partial.append(num)

    if (shortest_combination == None) or (len(partial) < len(shortest_combination)):
        shortest_combination = partial

Javascript 方法创建列表remainder_com副本,并附加了元素num。在您的方法中,您直接附加到partial 而不创建副本。因此,在每次迭代中,相同的列表将用于修改,这是不希望的。改成

# Creates a copy of `partial` with `num` appended
combination = partial[:] + [num]

if (shortest_combination == None) or (len(combination) < len(shortest_combination)):
    shortest_combination = combination

这会按预期输出[25, 25, 25, 25]

【讨论】:

  • 谢谢。我认为 partial 是一个局部变量,所以不能在递归调用堆栈中重用。
猜你喜欢
  • 2021-04-04
  • 1970-01-01
  • 2018-04-06
  • 2012-08-24
  • 2022-06-15
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
相关资源
最近更新 更多