Python版can_sum函数记忆化优化后全测试输出为True的问题排查
核心问题定位
出现计算结果不符合预期的根本原因,是Python可变默认参数的初始化机制和JavaScript存在本质差异,并非求和判断逻辑本身出错。
你在JS中给函数设置默认空对象参数时,每次函数调用都会在独立的执行上下文中新建一个空对象做缓存;但Python中,函数定义阶段就会仅创建一次memo={}这个空字典对象,后续所有没有显式传入memo的函数调用,全都会复用同一个全局字典实例——上一次函数调用存入的缓存值根本不会被清空,直接导致跨调用的结果污染。
异常结果的触发逻辑
- 第一次调用
can_sum(7,[2,3])执行完成后,memo字典中已经存储了递归过程中计算的所有中间值结果,包括键7对应的True值 - 第二次调用
can_sum(7,[7,5,3,4])时,函数入口会直接检查7 in memo,直接从老缓存中取出True返回,完全不会执行后续的求和判断逻辑 - 第三次调用
can_sum(7,[2,4]),本应返回False,却因为老缓存中已经存在键7对应的True值,直接返回缓存结果,和你实际观察到的“所有输出都是True”的现象完全匹配 - 最后调用的
can_sum(300,[7,14]),也是因为缓存中早已存在递归过程命中的中间值结果,不会重新基于当前传入的数字列表计算正确结果
注:你代码中重复写了两次if targetSum<0判断,属于冗余代码,并非导致异常的原因,可直接删除。
修复方案
规避Python可变默认参数共享问题的标准写法是:将memo的默认值设置为None,在函数内部判断到memo为None时,再为当前这次独立的计算任务新建独立的空缓存字典,从根源上避免不同调用之间的缓存污染。
修复后的完整代码如下:
def can_sum(targetSum, numbers, memo=None): # 仅当没有传入自定义memo时,为当前计算任务新建独立空缓存 if memo is None: memo = {} if targetSum < 0: return False if targetSum in memo: return memo[targetSum] if targetSum == 0: return True for n in numbers: remainder = targetSum - n if can_sum(remainder, numbers, memo): memo[targetSum] = True return True memo[targetSum] = False return False
修复后逐次调用的结果完全和预期一致:
can_sum(7,[2,3])→ Truecan_sum(7,[7,5,3,4])→ Truecan_sum(7,[2,4])→ Falsecan_sum(8,[2,3,5])→ Truecan_sum(300,[7,14])→ False
内容的提问来源于stack exchange,提问作者Ramyak Sharma
相关产品推荐
相关产品推荐

