为什么要接触全排列
全排列在笔试面试中很热门,因为它难度适中,既可以考察递归实现,又能进一步考察非递归的实现,便于区分出考生的水平。所以在百度和迅雷的校园招聘以及程序员和软件设计师的考试中都考到了,因此本文对全排列作下总结帮助大家更好的学习和理解。对本文有任何补充之处,欢迎大家指出。
全排列原理解析
全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。待会以{1, 2, 3, 4, 5}为例说明如何编写全排列的递归算法。
全排列算法解析
首先来看看题目是如何要求的(百度迅雷校招笔试题)。
用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列,
如 abc 的全排列: abc, acb, bca, dac, cab, cba
为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。
根据上面的规律和算法分析以后来给出简易代码(貌似不太复杂,却我感觉很绕,建议多DEBUG,因为我也是这样分析的!)
#include <iostream>
using namespace std;
int n = 0;
void cout1(int list[])
{
for (int c = 0; c<=1; c++)
{
printf("%d ", list[c]);
}
printf("\n");
}
void swap(int *a, int *b)
{
int m;
m = *a;
*a = *b;
*b = m;
}
void perm(int list[], int k, int m)
{
int i;
if(k > m) //k=0 m=1 ---1 :k =1: k=2:
{
for(i = 0; i <= m; i++)
printf("%d ", list[i]);
printf("\n");
n++;
}
else
{
for(i = k; i <= m; i++) //k=0,m=1 --1 :k =i =1:
{
swap(&list[k], &list[i]);
// cout1(list);
perm(list, k + 1, m); //m =k =1:
//1
swap(&list[k], &list[i]);
}
}
}
int main()
{
int list[] = {1, 2,3 };
perm(list, 0, 2);
printf("total:%d\n", n);
system("pause");
return 0;
}
运行效果如下:
OK !请细细的Debug,是不是有新的发现呢?如果我全改成相同的,又会有什么发现呢?改成222哈!
运行效果如下:
先消化那么多吧,下面我将去掉重复的全排列的递归实现和使用全排列的非递归实现!
(如果您有更有效率的算法请您与我们共同分享!)
期待将持续更新!
syw_selfimpr新浪微博地址: http://weibo.com/u/2945271402