目录

Chapter-2 Search 第2章 搜索 - Recursion 递归

优质
小牛编辑
117浏览
2023-12-01

问题

序列 s 有 n 个成员 [x_1,x_2, cdots ,x_n] ,每个成员可以选取 [1,2, cdots ,m] 这 m 种值。例如当 n = 5 , m = 3 时,序列 s 有如下排列组合:


[1,1,1,1,1], [1,1,1,1,2], [1,1,1,1,3], [1,1,1,2,1] cdots

求 s 的所有排列组合。(与本节的<BruteForce>问题一样)

解法

<BruteForce>存在一个问题,外围for循环的数量是固定的,无法改变。因此我们用递归来解决这个问题。假设序列 s 从长度 0 增长到 n 。在长度为 i 的基础上,我们找出序列 s 增加一个元素,成为长度为 i+1 时的所有可能的排列组合(其中 0 le i lt n )。初始化时令序列为空 s = [] 。

(1) 将序列 s 的长度增加到 1 ,第 1 个元素(唯一的元素) x_1 有 m 种选择,即长度为 1 的序列 s 有 m 个排列组合:


[1_1]


[2_1]


cdots


[m_1]

(2) 将序列 s 的长度增加到 2 ,得到数组 s = [x_1,x_2] ,元素 x_2 的选择可以看作在第 (1) 轮的每个选择的基础上继续选择。对于 [1_1] 可以得到 m 个排列组合:


[1_1,1_2]


[1_1,2_1]


cdots


[1_1,m_1]

第 (2) 轮操作后共有 m^2 个排列组合。重复 n 次这样的操作,可以得到 m^n 个排列组合。

实际编写代码中,在递归方程中传入一个参数 prev in [0,n) , prev 从 0 开始,序列 s 中的成员 x{prev} 可以取值 i in [1,m] ,然后 prev = prev+1 ,继续考虑序列 s 中的下一个成员 x{prev+1} 。这样直到当 n 个成员都选择了一个值时,即产生序列 s 的一种排列组合。通过递归可以退回上一个函数栈,从而让每个成员 x_{prev} 都可以重新选择。

对于成员数量为 n ,每个成员有 m 种值的序列 s ,遍历所有排列组合的时间复杂度 O(m^n) 。