1.全排列的定义和公式: 从n个数中选取m(m<=n)个数按照一定的顺序进行排成一个列,叫作从n个元素中取m个元素的一个排列。由排列的定义,显然不同的顺序是一个不同的排列。从n个元素中取m个元素的所有排列的个数,称为排列数。从n个元素取出n个元素的一个排列,称为一个全排列。全排列的排列数公式为n!,通过乘法原理可以得到。
2.时间复杂度: n个数(字符、对象)的全排列一共有n!种,所以全排列算法至少时O(n!)的。如果要对全排列进行输出,那么输出的时间要O(n*n!),因为每一个排列都有n个数据。所以实际上,全排列算法对大型的数据是无法处理的,而一般情况下也不会要求我们去遍历一个大型数据的全排列。
3.全排列算法解决思路:假设现有1 2 3 三个数,我们构造全排列的方式为:先确定第一位1,然后可选(2,3)(3,2)作为后序的排列组合,这样以1作为首位的全排列就有(1,2,3)(1,3,2)两种,然后再以2作为第一位,从而构造出(2,1,3)(2,3,1).最后是(3,1,2)(3,2,1)。即求n个数的全排列=先枚举确立一个数,然后求n-1的全排列。这与我们常见的回溯递归法基本一样。当所有的位数都确定完毕,即成为一组完整的排列数,也就是递归的出口。
4.全排列算法代码:
void Permutation(int A[], int m, int n){ if (m == n) { Print(A, n); Count++; } else { for (int i = m; i < n; i++) { Swap(A[m], A[i]); Permutation(A, m + 1, n); Swap(A[m], A[i]); } }}
当m==n即所有位数都确定,即为一组完整的排列数,否则枚举确定第m位数(使第m位依次与后面位数交换),递归返回后再回溯还原。
注:Print函数功能为输出A数组前n位,Swap函数为交换两个数,Count为全局变量,记录排列数
void Swap(int &a, int &b){ a == b ? 0 : a ^= b ^= a ^= b;}void Print(int A[], int n){ for (int i = 0; i < n; i++) { printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); }}
外部调用:
int main(){ int A[] = { 1,2,3,4 }; int n = sizeof(A) / sizeof(A[0]); Permutation(A, 0, n); printf("%d\n", Count); system("pause"); return 0;}
5.时间复杂度
此算法可以列出从A数组中第m个元素到第n个元素的所有排列,注意m,n可以在任意位置。算法的复杂度在于for循环和递归,最大的for是n,递归为n-1所以为O(n*n-1*n-2*...1)=O(n!)
6.运行截图
注:函数调用意为:从第2位到第4位(不包括)的全排列,故收影响的排列只有(1,2,3,4,5)(1,2,4,3,5)
由于我们的Print函数是从0位输出到n位的,所以只打印了0-3位,此样例只是辅助说明Permutation函数中m和n参数的作用。
7.参考文档
https://wenku.baidu.com/view/8c79a2facc17552706220880.html
共同学习,写下你的评论
评论加载中...
作者其他优质文章