递归——全排列问题(Full Permutation)
废话少说,首先看定义:
全排列(Full Permutation),一般把1~n这n个整数按某个顺序摆放的结果称为这n个整数的一个排列 ,而全排列指这n个整数能形成的所有排列。例如对1、2、3这三个整数来说, (1, 2, 3)、(1, 3, 2)、(2, 1, 3)、(2, 3, 1)、(3, 1, 2)、(3, 2, 1)就是1~3的全排列。
现在需要实现按字典序从小到大的顺序输出 1~n 的全排列,其中 (a1, a2, …, an) 的字典序小于 (b1, b2, …, bn) 是指存在一个 i ,使得 a1=b1, a2=b2, …, a(i-1) = b(i-1)、ai<bi 成立。因此上面n=3的例子就是按字典序从小到大的顺序给出的。
按字典序排列用大白话的意思就是:任取排列结果中的两个元素作比较,例如(2, 1, 3)和(2, 3, 1),两个元素的第一位相等都是2(比较下一位),第二位 1 < 3,所以按从小到大的顺序排列时, (2, 1, 3)一定排在(2, 3, 1)前面。
用递归的角度去考虑,如果把问题描述成
”输出1~n这n个整数的全排列“
那么它就可以被分为若干个子问题:
”输出以1开头的全排列“、”输出以2开头的全排列“ … ”输出以n开头的全排列“。
在实现代码前,我们需梳理一下重要逻辑:
- 我们需要一个int型数组 P, 来存放当前的排列;
- 排列中的元素不能重复,例如1~3的全排列,是不能出现(1,2,2)这样的元素的,每个数字能且仅能出现一次。于是我们可以设定一个bool型的数组 Table[x],数组的下标代表当前的数字,默认值为false,当整数x已经在当前排列中使用过的时候,我们就将 Table[x] 的值设置为true。
- 当我们按顺序往P的第1位到第n位中填入数字的时候,不妨假设当前已经填好了P[1] ~ P[index-1],正准备填P[index]。显然我们需要for循环遍历1~n,来确定当前的数字x是否在已经枚举的数字中出现过(即Table[x] == false)。若出现过,我们就跳过这个数字去看下一个数字Table[x+1],若没有出现过,就把他填入P[index],同时将Table[x]的值置为true,然后进入递归去处理第index+1位;当排列的全部递归完成时,再将Table[x]的所有值还原为false,以便下一次for循环的判断。
- 在递归进行的最后的时候,我们需要规定一个跳出的边界的条件。当P的index到达 n+1 时,说明P的第1~n位都已经填好了,此时便可跳出递归。
如果你已经理解了上述的逻辑推理,可以试着自己先用代

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



