分类: C/C++
2015-03-19 19:33:06
定义一个数组,编程打印它的全排列。比如定义:
#define N 3 int a[N] = { 1, 2, 3 };
则运行结果是:
$ ./a.out 1 2 3 1 3 2 2 1 3 2 3 1 3 2 1 3 1 2 1 2 3
程序的主要思路是:
把第1个数换到最前面来(本来就在最前面),准备打印1xx,再对后两个数2和3做全排列。
把第2个数换到最前面来,准备打印2xx,再对后两个数1和3做全排列。
把第3个数换到最前面来,准备打印3xx,再对后两个数1和2做全排列。
可见这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题
解题过程:
(1) 当 N = 1的时候,则直接打印数列即可。
(2) 当 N = 2的时候,设数组为 [1, 2]
打印a[0], a[1] (即1,2)
交换a[0],a[1]里面的内容
打印a[0],a[1] (此时已变成了 [2, 1] )
(3) 当 N = 3的时候,数组为 [1, 2, 3]
a. 把1放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印2,3的全排列(即a[1], a[2]的全排列)
1 2 3
1 3 2
b. 把2放在a[0]的位置(这时候需要交换原数组的a[0]和a[1]),然后打印1, 3的全排列
2 1 3
2 3 1
打印完后再换回原来的位置,即1还是恢复到a[0],2还恢复到a[1]的位置
c. 把3放在a[0]的位置 (这时候需要交换的是原数组的a[0]和a[2]),然后打印1, 2的全排列
3 2 1
3 1 2
打印完后再换回原来的位置,即1还是恢复到a[0],3还恢复到a[2]的位置,
至此全排列完成
(4)N = 4, 5, 6....的思路与此相同
点击(此处)折叠或打开
点击(此处)折叠或打开
先看一个例子:
C(5,3) = 10
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
分析
1 | 2 3
1 | 2 4
1 | 2 5
1 | 3 4
1 | 3 5
1 | 4 5
------ C(4, 2)∵可以在{2, 3, 4, 5}中挑2个出来。
2 | 3 4
2 | 3 5
2 | 4 5
------ C(3, 2)∵可以在{3, 4, 5}中挑2个出来。
3 | 4 5
------ C(2, 2)∵只能在{4, 5}中挑2个出来。
这样就很容易写出递归算法来:
点击(此处)折叠或打开
点击(此处)折叠或打开