全排列问题
简单来说,将1~n个整数按某个顺序摆放的结果称为这n个整数的一个排列。全排列指这n个整数能形成的所有不同的排列。
eg:1, 2, 3的全排列为
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
现在我们来谈谈通过递归来解决这一问题:
想象一下,上帝创造了三扇门,分别标记为1,2,3,开始时这三扇门都是关闭的。
【1】 【2】 【3】
现在到你开门的时候了。
因为开始时三扇门都是关闭的,因此你可以选择开启任意一扇门。
- 现在假设你打开了第一扇门【1】,你发现在你面前又出现了两扇门
【2】 【3】
因为你已经打开了第一扇门,因此你的选择中没有第一扇门【1】 - 假设你又选择了打开第二扇门【2】,此时你的面前又出现了一扇门
【3】
同样,因为你已经打开了第一扇门和第二扇门,所以你没有这两个选择 - 这次你没得选,你打开第三扇门,得到序列(1,2,3)
- 你退出第三扇门,关闭它,退出第二扇门,关闭它。现在只有第一扇门是打开的,回到步骤2中,【2】你已经探索过了;这一次你选择打开【3】。
- 你发现只有第二扇门【2】,打开它,得到序列(1,3,2)
- 这一次你退出【2】,关闭它,退出【3】,关闭它,退出【1】关闭它。
后面【2】,【3】是一样的。
用代码来描述上述问题
#include <cstdio>
const int maxn = 100;
int P[maxn]; //存放当前序列
int hashTable[maxn] = {false}; //一开始所有门都是关闭的
int n; //序列长度
void generateP(int index){ //开门
if(index = n + 1){ //递归基,打开门发现只有墙了
for(int i = 1; i <= n; i++){
printf("%d ", P[i]);
}
printf("\n");
return;
}
for(int x = 1; x <= n; x++)
{
if(hashTable[x] == false) //门在关闭的时候才能打开
{
P[index] = x;
hashTable[x] = true; //标记刚才打开的门
generateP(index + 1); //继续开门
hashTable[x] = false; //标记关闭的门
}
}
}
int main()
{
n = 3;
generateP(1);
return 0;
}