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

Python递归函数中如何正确存储矩阵列表形式的N皇后求解结果

N皇后回溯存储结果异常问题解答

核心原因

Python中列表是引用传递的可变对象,你代码里的问题本质和列表维度没有直接关系,核心是两点:

  • 整个回溯流程中,你始终在操作全局唯一初始化的那一个board对象:所有放皇后、回溯撤销皇后的操作,都是在这个对象上做原地修改,从来没有生成过新的board对象。
  • 你写res.append(board)时,存入res的不是当前棋盘状态的快照副本,而是这个全局board对象的内存地址引用。也就是说res里存的所有元素,本质都指向同一个board列表——后续回溯把Q改回.的时候,res里已经存的“解”自然会跟着一起变,最后所有存进去的内容都会变成回溯完成后的全.空棋盘。

为什么有人存一维列表不用deepcopy?

这是场景差异,不是列表维度的魔法:

  • 如果回溯一维列表时用的是原地修改的写法(比如path.append(val); backtrack(); path.pop()),直接res.append(path)会出现和你完全一样的问题,存进去的结果会跟着回溯被修改,这种场景哪怕是一维列表也必须做拷贝。
  • 你看到的不需要拷贝的一维列表场景,基本都是用了生成新对象的写法:比如传参时写backtrack(path + [val]),这种写法每次递归都会生成一个全新的列表对象,append之后原路径不会再被修改,自然不需要额外拷贝。

为什么二维列表浅拷贝没用?

浅拷贝(比如board.copy()、list(board))只会复制最外层的列表容器,内层嵌套的每一行列表仍然是原对象的引用。回溯时修改内层行里的字符,浅拷贝出来的对象内容还是会同步变化,所以这种嵌套可变对象的场景,要么用copy.deepcopy()做全量拷贝,要么手动生成全新的结果对象。

更高效的修复方案

除了用deepcopy之外,找到合法解时直接生成不可变的字符串结果存入res即可,不需要额外导入copy模块,性能也更好,把你标注的混淆位置的代码替换成下面的内容就行:

# 原错误写法:res.append(board)
res.append( [''.join(row) for row in board] )

这段列表推导会遍历棋盘的每一行,把字符列表拼接成不可变的字符串,最终生成一个和原board完全独立的新列表,后续回溯修改原board不会对已经存入res的解产生任何影响。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:42:15