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

移除else为何导致Python递归permute函数重复输出结果?

为什么移除else后排列结果会重复两次?

核心原因是:移除else并取消缩进后,递归函数的终止条件代码块和后续的循环代码块会被同时执行,导致底层的递归调用会额外生成一份重复的排列,最终上层递归把这个重复放大,让每个最终排列都出现两次。

咱们先把两种代码的结构摆出来,对比着看就清楚了:

带else的正确版本(结果唯一)

def permute(nums):
    if len(nums) <= 1:
        # 终止条件:只有0个或1个元素时,直接返回自身作为唯一排列
        yield nums
    else:
        # 非终止情况:遍历每个元素,递归生成剩余元素的排列,再拼接
        for i in range(len(nums)):
            for p in permute(nums[:i] + nums[i+1:]):
                yield [nums[i]] + p

这里的逻辑很清晰:当满足len(nums)<=1时,只会执行yield nums,不会进入后面的循环——else确保了两个分支互斥,要么走终止逻辑,要么走递归拼接逻辑。

移除else后的错误版本(结果重复)

def permute(nums):
    if len(nums) <= 1:
        yield nums
    # 注意:这里没有else了,不管上面的if是否触发,都会执行这个循环
    for i in range(len(nums)):
        for p in permute(nums[:i] + nums[i+1:]):
            yield [nums[i]] + p

问题就出在没有else的隔离上:当len(nums)<=1时,程序会先执行yield nums,然后继续执行后面的循环!

咱们拿最底层的递归调用举例,比如permute([3]):

  1. 首先触发if len(nums)<=1,yield [3]——这是第一次输出[3]。
  2. 接着执行后面的循环:range(len([3]))是range(1),也就是i=0。
  3. 调用permute(nums[:0] + nums[1:]),也就是permute([])。
  4. permute([])同样触发if len(nums)<=1,yield [],然后循环因为range(0)不会执行,所以返回一个空列表的生成器。
  5. 于是yield [3] + [],也就是第二次输出[3]。

看到没?permute([3])会生成两个完全一样的[3]!

当上层递归调用permute([32,3])时:

  • 遍历i=0(取32),调用permute([3])得到两个[3],于是生成[32,3]两次。
  • 遍历i=1(取3),调用permute([32])得到两个[32],于是生成[3,32]两次。
    最终permute([32,3])会输出4个结果,每个排列重复两次。

以此类推,当调用permute([12,32,3])时,每一层递归都会把重复的结果再传递下去,最终每个3元素的排列都会被生成两次,总共12个输出(原本应该是6个唯一排列)。

总结一下:else的作用是确保终止条件和递归逻辑二选一,移除它之后,终止条件的代码执行完还会跑一遍递归逻辑,导致底层生成重复的基础排列,最终上层所有排列都跟着重复了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:56:11