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

递归全局变量问题:数组全排列结果异常及无全局变量实现方案

嗨,我来帮你拆解和解决这两个问题:

问题分析与解决方案

一、类变量ans输出异常的原因

你遇到的重复排列问题,核心有两个关键原因:

  1. 未复制acc就添加到结果中:你在helper函数里直接把acc添加到self.ans,但acc是可变的列表对象,后续的acc.pop()操作会修改这个对象的内容。因为self.ans里存的是acc的引用而非独立副本,所以之前添加的结果会跟着acc的修改同步变化,最终出现重复的排列条目。
  2. 多余的global ans声明:你的ans是类属性,用self.ans访问即可,global ans这行代码没有实际作用,反而容易造成混淆。

比如你输出里的[[1, 3, 2], [1, 3, 2]],就是因为第一次添加的[1,2,3]和第二次添加的[1,3,2]其实是同一个列表对象的引用,当acc被修改为[1,3,2]时,之前的条目也跟着变了。

修正后的类变量版本代码

只需要在添加到ans时,复制一份acc的副本(因为acc里是整数,浅拷贝acc.copy()就足够,不需要deepcopy):

from copy import deepcopy
from typing import List

class Solution:
    ans = []
    
    def permute(self, nums: List[int]) -> List[List[int]]:
        if nums is None:
            return None
        # 重要:每次调用permute时清空ans,避免多次调用累积旧结果
        self.ans.clear()
        self.helper(nums, [])
        return self.ans
    
    def helper(self, rem, acc):
        # 移除无用的global ans声明
        rem_cpy = deepcopy(rem)
        if len(rem) == 0:
            # 添加acc的副本,而非引用
            self.ans.append(acc.copy())
            print(self.ans)
            return
        for i in range(len(rem_cpy)):
            acc.append(rem_cpy[i])
            rem = rem_cpy[:i] + rem_cpy[i+1:]
            self.helper(rem, acc)
            acc.pop()

二、不使用全局/类变量的递归实现

要摆脱全局变量,我们可以让helper函数直接返回当前剩余元素能生成的所有排列,上层函数合并这些子结果即可。核心思路是:

  • 当剩余元素为空时,返回只包含当前路径副本的列表;
  • 遍历每个剩余元素,将其加入当前路径,递归处理剩余元素,把递归返回的所有排列合并到结果中,最后回溯弹出当前元素。

实现代码

from typing import List

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        if nums is None:
            return None
        return self.helper(nums, [])
    
    def helper(self, rem, acc):
        if not rem:
            # 返回包含当前路径副本的列表
            return [acc.copy()]
        result = []
        for i in range(len(rem)):
            acc.append(rem[i])
            # 递归获取子排列,并合并到结果中
            sub_perms = self.helper(rem[:i] + rem[i+1:], acc)
            result.extend(sub_perms)
            acc.pop()
        return result

更简洁的无回溯写法(无需pop)

这种写法每次递归都创建新的列表,完全避免了共享可变对象的问题,代码也更直观:

from typing import List

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        if not nums:
            return [[]]
        result = []
        for i in range(len(nums)):
            # 固定当前元素,递归处理剩余元素的所有排列
            for perm in self.permute(nums[:i] + nums[i+1:]):
                result.append([nums[i]] + perm)
        return result

这个版本里,每次递归都会生成新的排列列表,根本不需要全局变量或者类属性,逻辑也更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:07:50