移除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]):
- 首先触发
if len(nums)<=1,yield [3]——这是第一次输出[3]。 - 接着执行后面的循环:
range(len([3]))是range(1),也就是i=0。 - 调用
permute(nums[:0] + nums[1:]),也就是permute([])。 permute([])同样触发if len(nums)<=1,yield [],然后循环因为range(0)不会执行,所以返回一个空列表的生成器。- 于是
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
相关产品推荐
相关产品推荐

