You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python回溯算法中递归全局变量问题及替代方案咨询

回溯算法常见问题解答

嘿,我来逐个拆解你遇到的这些问题:

1. 全局列表定义与global关键字报错问题

你碰到的global name 'res' is not defined错误,大概率是因为**global声明的位置不对**,或是在某些运行环境里变量作用域的解析出了小问题。其实对于列表这种可变对象,如果你只是做原地修改(比如append、pop),哪怕不声明global也能访问全局变量——前提是你没在函数内部重新赋值这个变量(比如写res = []会创建局部变量,直接覆盖全局的res)。

如果确实要用到全局变量,规范的做法是把global res放在函数的最开头(任何使用该变量的代码之前),比如:

seen = []
res = []

def func(candidates, k, anc_choice):
    global res  # 放在函数开头,让解析器明确要调用全局的res
    # ... 后续代码不变

不过全局变量并不是回溯算法的最优解,接下来咱们说更稳妥的方案。

2. 无需全局变量获取结果的通用方法

当然有!最常用的两种思路:

  • 将结果列表作为参数传递:递归调用时把结果列表传入函数,每次找到符合条件的组合就直接添加进去。这种方式没有全局变量的副作用,也更符合函数式编程的逻辑。
  • 用函数返回值收集结果:让递归函数返回当前分支下找到的所有组合,在父调用里把这些结果合并起来。

举个参数传递的改造示例:

def func(candidates, k, anc_choice, res):
    if sum(anc_choice) == k:
        # 这里要复制列表,后面会解释原因
        res.append(list(anc_choice))
        return
    for c in candidates:
        if sum(anc_choice) + c <= k:  # 提前判断,减少不必要的递归
            anc_choice.append(c)
            func(candidates, k, anc_choice, res)
            anc_choice.pop()

# 调用时初始化结果列表
res = []
func([2,3,6,7], 7, [], res)
print(res)

3. res.append(anc_choice)无法得到正确结果的原因

这是回溯里非常容易踩的坑:你添加到res里的是anc_choice这个列表对象的引用,而不是它当前内容的副本。

递归过程中,你一直在对同一个anc_choice列表做append和pop操作,等递归结束后,这个列表已经被还原到初始状态了。所以最后res里的所有元素指向的都是同一个空(或最终状态)的列表,自然看不到正确结果。

解决办法很简单:添加的时候创建列表的副本,比如:

res.append(list(anc_choice))  # 或者用 anc_choice.copy()、[x for x in anc_choice]

另外,你用seen集合去重的方式也有隐患:比如[2,2,3]的集合是{2,3},如果后续生成类似[2,3,2]的组合(虽然当前逻辑不会,但候选集有重复元素时就会出问题),集合会误判为同一组合。更好的去重方式是先给候选集排序,然后递归时限制只能选择当前索引及之后的元素,从根源避免生成重复组合:

def func(candidates, k, start, anc_choice, res):
    if sum(anc_choice) == k:
        res.append(list(anc_choice))
        return
    for i in range(start, len(candidates)):
        # 跳过重复元素(候选集有重复时生效)
        if i > start and candidates[i] == candidates[i-1]:
            continue
        if sum(anc_choice) + candidates[i] <= k:
            anc_choice.append(candidates[i])
            # 下一次递归从i开始,避免回头选前面的元素,杜绝排列组合
            func(candidates, k, i, anc_choice, res)
            anc_choice.pop()

candidates = [2,3,6,7]
candidates.sort()  # 先排序
res = []
func(candidates, 7, 0, [], res)
print(res)

这样改造后,既能正确收集结果,又能高效避免重复组合,不需要额外的seen集合。

内容的提问来源于stack exchange,提问作者crazyy_photonn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:13:52