当前位置:   article > 正文

Leetcode中级算法-全排列

生成从n选m的所有排列算法_leetcode

全排列算法思想:

1. 全排列的定义和公式:

   从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。由排列的定义,显然不同的顺序是一个不同的排列。从n个元素中取m个元素的所有排列的个数,称为排列数。从n个元素取出n个元素的一个排列,称为一个全排列。

    公式:全排列数f(n) = n! (定义0!=1)
2. 时间复杂度:

   n个数(字符、对象)的全排列一共有n!种,所以全排列算法至少时间O(n!)的。如果要对全排列进行输出,那么输出的时间要O(n∗n!),因为每一个排列都有n个数据。所以实际上,全排列算法对大型的数据是无法处理的,而一般情况下也不会要求我们去遍历一个大型数据的全排列。

3. 全排列的初始思想

   为了解决一个算法问题,我们选择从基本的想法做起。先回顾一下我们自己是如何写一组数的全排列的:1,3,5,9
首先肯定是 :

  1. 1 ,[359的全排列]
  2. 3 ,[159的全排列]
  3. 5 ,[319的全排列]
  4. 9 ,[351的全排列]

很显然这是一个递归的思路,那么我们根据该想法写出来的初版代码就是:

  1. void permute(vector<int> &nums ,....... ){
  2. for (int i = 0 ; i != n ; ++i )
  3. {
  4. swap(nums,0,i);
  5. //将第i个数与第一个数交换,从而得到第一个数的所有情况 1,3,5,9
  6. resove(nums , ..... ); //其后的元素再进行全排列。
  7. }
  8. }

给函数加上参数之后就是:

  1. void permute(vector<int> &nums ,int p , int q ){
  2. for (int i = 0 ; i != n ; ++i )
  3. {
  4. swap(nums,0,i);
  5. resove(nums , 1, n-1 ); //将后面的1~n-1 个元素再进行全排列。
  6. }
  7. }

因为我们不一定就是从第一个元素到最后一个元素进行全排列 ,所以我们必须修改循环条件,使之具有普遍性:

  1. //拿 p~q 之间的元素进行全排列
  2. void permute(vector<int> &nums ,int p , int q ){
  3. for (int i = p ; i != q ; ++i )
  4. {
  5. swap(nums,p,i);
  6. resove(nums , p+1, q ); //将后面的 p+1~q 个元素再进行全排列。
  7. }
  8. }

OK,下面才是我们的重点内容!!!动脑克啦,

  假如,我们交换到了[3,1,5,9],接下来需要由5来打头,如果直接将5 和第一个元素交换,那么序列就变成了[5,1,3,9] ,很显然这是极其不正确的。所以我们还需要在由5来打头之前,将[3,1,5,9]进行还原 。

  1. void permute(vector<int> &nums ,int p , int q ){
  2. if(p == q) {
  3. 在这里打印序列即可 !
  4. }
  5. for (int i = p ; i != q ; ++i )
  6. {
  7. swap(nums,p,i);
  8. resove(nums , p+1, q );
  9. swap(nums,p,i);//要还原,确保初始状态一致。
  10. }
  11. }
4.全排列的非去重递归算法

   算法思路:全排列可以看做固定前i位,对第i+1位之后的再进行全排列,比如固定第一位,后面跟着n-1位的全排列。那么解决n-1位元素的全排列就能解决n位元素的全排列了,这样的设计很容易就能用递归实现

题意:
  1. 给定一个没有重复数字的序列,返回其所有可能的全排列。
  2. 示例:
  3. 输入: [1,2,3]
  4. 输出:
  5. [
  6. [1,2,3],
  7. [1,3,2],
  8. [2,1,3],
  9. [2,3,1],
  10. [3,1,2],
  11. [3,2,1]
  12. ]

解决过程中遇到的问题:

c++ STL中怎么定义一个二维向量(vector)

  1. vector<类型> name(size,init_value);
  2. vector<int> temp(num,0);//num为向量行数,0为初始化值
  3. vector<vector<int> > test(num,TT);
  4. //前面一个参数表示向量个数,后面参数表示是怎样的一种向量
  5. 最后就相当于定义了一个test[num][num]的数组

如何比较快速的求得一个数的阶乘

  1. 定义寄存器变量
  1. #include<iostream>
  2. using namespace std;
  3. int fac(int);
  4. int main()
  5. {
  6. int n;
  7. while(cin>>n)
  8. {
  9. cout<<n<<"!= "<<fac(n)<<endl;
  10. }
  11. return 0;
  12. }
  13. int fac(int x)
  14. {
  15. register int i,f=1; //定义寄存器变量
  16. for(i=1;i<=x;i++)
  17. f*=i;
  18. return f;
  19. }
  1. 利用了数组记录已得到的结果,并在计算下一个结果时利用了已得到的结果。
  1. #include<iostream>
  2. using namespace std;
  3. int a[11];
  4. void init();
  5. int main()
  6. {
  7. init();
  8. int n;
  9. while(cin>>n)
  10. {
  11. cout<<n<<"!= "<<a[n]<<endl;
  12. }
  13. return 0;
  14. }
  15. void init()
  16. {
  17. int i;
  18. a[0]=1;
  19. for(i=1;i<=10;i++)
  20. a[i]=i*a[i-1];
  21. }
  1. 递归 (略)
  2. 使用静态局部变量
  1. #include<iostream>
  2. using namespace std;
  3. int fac(int);
  4. int main()
  5. {
  6. int i;
  7. for(i=1;i<=10;i++)
  8. {
  9. cout<<i<<"!= "<<fac(i)<<endl;
  10. }
  11. return 0;
  12. }
  13. int fac(int x)
  14. {
  15. static int f=1; //静态局部变量
  16. f*=x;
  17. return f;
  18. }

ps:推荐第二种!!!!

通过源代码:

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4. using namespace std;
  5. using Iterator = vector<int>::iterator ;
  6. using VV = vector<vector<int> > ;
  7. class Solution {
  8. public:
  9. void resove(VV &intVec, vector<int> &nums ,
  10. Iterator be , Iterator &ed ) {
  11. if (be == ed ) {
  12. intVec.push_back(nums);
  13. }
  14. else {
  15. for (auto it = be ; it != ed ; ++it )
  16. {
  17. swap(*it, *be);
  18. resove(intVec, nums , be + 1 , ed );
  19. swap(*it, *be);
  20. }
  21. }
  22. }
  23. vector<vector<int>> permute(vector<int>& nums) {
  24. VV intVec ;
  25. Iterator be = nums.begin() , ed = nums.end() ;
  26. resove(intVec, nums , be, ed ) ; // 3
  27. return intVec ;
  28. }
  29. } ;

转载于:https://www.cnblogs.com/Tattoo-Welkin/p/10335275.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/256991
推荐阅读
相关标签
  

闽ICP备14008679号