简体   繁体   English

如何正确实现memoization?

[英]How to correctly implement memoization?

I have been spending way too much time on a programming challenge:我在编程挑战上花费了太多时间:

Given a budget and a set of prices, compute all unique combinations on how to spend the entire budget.给定一个预算和一组价格,计算如何花费整个预算的所有独特组合。

Example例子

Input输入

budget = 100
prices = [25, 50]

Output Output

[[25, 25, 25, 25], [25, 25, 50], [25, 50, 25], [50, 25, 25], [50, 50]]

I have implemented a brute force solution in Python that works correctly:我在 Python 中实施了一个正常工作的蛮力解决方案:

def spend_the_budget(budget: int, prices: list) -> list:
    if budget == 0:
        return [[]]
    if budget < 0:
        return None

    combinations = []
    for price in prices:
        remainder = budget - price
        remainder_combinations = spend_the_budget(remainder, prices)
        if remainder_combinations is not None:
            for remainder_combination in remainder_combinations:
                remainder_combination += [price]
                combinations.append(remainder_combination)
    return combinations

However, this has obviously exponential time complexity and therefore doesn't scale in an acceptable fashion.然而,这显然具有指数时间复杂度,因此不能以可接受的方式扩展。 Therefore I'd like to add memoization but can't seem to get it to work:因此我想添加记忆,但似乎无法让它工作:

def spend_the_budget_memoized(budget: int, prices: list, memo: dict = {}) -> list:
    if budget in memo:
        return memo[budget]
    if budget == 0:
        return [[]]
    if budget < 0:
        return None

    combinations = []
    for price in prices:
        remainder = budget - price
        remainder_combinations = spend_the_budget_memoized(remainder, prices, memo)
        if remainder_combinations is not None:
            for remainder_combination in remainder_combinations:
                remainder_combination += [price]
                combinations.append(remainder_combination)
    memo[budget] = combinations
    return combinations

Weirdly enough however, this yields an incorrect result and I just can't wrap around my head as to what I did wrong here:然而,奇怪的是,这会产生一个不正确的结果,我无法理解我在这里做错了什么:

Output Output

[[25, 25, 25, 50, 25, 25, 50], [50, 25, 25, 50], [25, 25, 25, 50, 25, 25, 50], [25, 25, 25, 50, 25, 25, 50], [50, 25, 25, 50]]
for remainder_combination in remainder_combinations:
                remainder_combination += [price]
                combinations.append(remainder_combination)

When you iterate over remainder_combinations you are iterating over the same copy which is stored in memo .当您迭代remainder_combinations组合时,您正在迭代存储在memo中的同一个副本。 Use list.copy() instead,使用 list.copy() 代替,

for remainder_combination in remainder_combinations:
                temp = remainder_combination.copy()
                temp += [price]
                combinations.append(temp)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM