当前位置:   article > 正文

回溯算法(全排列问题)_回溯法求全排列问题的时间复杂度

回溯法求全排列问题的时间复杂度

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

从n个数中选取m(m<=n)个数按照一定的顺序进行排成一个列,叫作从n个元素中取m个元素的一个排列。由排列的定义,显然不同的顺序是一个不同的排列。从n个元素中取m个元素的所有排列的个数,称为排列数。从n个元素取出n个元素的一个排列,称为一个全排列。全排列的排列数公式为n!,通过乘法原理可以得到。

2.时间复杂度

n个数(字符、对象)的全排列一共有n!种,所以全排列算法至少时间O(n!)

的。如果要对全排列进行输出,那么输出的时间要O(nn!),因为每一个排列都有n个数据。

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

举例:简单点拿常数1,2,3来说:首先对1进行全排列,首先保持第一个不变,对【2,3】进行全排列。同样地,我们先保持2不变,对【3】进行全排列。故排列为【1,2,3】 。接下来不能以2打头了,2,3相互交换,得到

【1,3,2】。 所以1的全排列为【1,2,3】,【1,3,2】 。同理对2,3元素同样处理。

递归代码:

  1. void prim(int a[],int start,int end){
  2. if(start==end){
  3. for(int i = 0;i<=end;i++){ //当递归到开始节点与结束点相同时,打印结果。
  4. cout<<a[i]<<" ";
  5. }
  6. cout<<endl;
  7. }
  8. /*
  9. *这里的递归理解:for循环实现对数组中第一个元素与其他元素交换(当然也包括本身),
  10. *然后进行相应递归求得其他每个元素对应的排列。
  11. *需要注意的是:交换后,要记得"回溯",保证元素的正常递归顺序。
  12. */
  13. else{
  14. for(int i = start;i<=end;i++){
  15. swap(a[start],a[i]); //与当前开始交换位置.
  16. prim(a,start+1,end);
  17. swap(a[start],a[i]); //交换位置,换回原来的情况。
  18. }
  19. }
  20. }

完整代码:

  1. /*
  2. @全排列问题
  3. */
  4. #include <iostream>
  5. #include <cstdio>
  6. #include <cstdlib>
  7. #include <cstring>
  8. using namespace std;
  9. void swap(int &a,int &b){ //注意要取地址(交换的应为值与位置)
  10. int item = a;
  11. a = b;
  12. b = item;
  13. }
  14. void prim(int a[],int start,int end){
  15. if(start==end){
  16. for(int i = 0;i<=end;i++){ //当递归到开始节点与结束点相同时,打印结果。
  17. cout<<a[i]<<" ";
  18. }
  19. cout<<endl;
  20. }
  21. /*
  22. *这里的递归理解:for循环实现对数组中第一个元素与其他元素交换(当然也包括本身),
  23. *然后进行相应递归求得其他每个元素对应的排列。
  24. *需要注意的是:交换后,要记得"回溯",保证元素的正常递归顺序。
  25. */
  26. else{
  27. for(int i = start;i<=end;i++){
  28. swap(a[start],a[i]); //与当前开始交换位置.
  29. prim(a,start+1,end);
  30. swap(a[start],a[i]); //交换位置,换回原来的情况。
  31. }
  32. }
  33. }
  34. int main()
  35. {
  36. int a[10] = {1,2,3};
  37. cout<<"元素全排列为:"<<endl;
  38. prim(a,0,2);
  39. return 0;
  40. }

【注1】swap(str[i],str[j]) //交换回来

当我们对序列进行交换之后,就将交换后的序列除去第一个元素放入到下一次递归中去了,递归完成了再进行下一次循环。这是某一次循环程序所做的工作,这里有一个问题,那就是在进入到下一次循环时,序列是被改变了。可是,如果我们要假定第一位的所有可能性的话,那么,就必须是在建立在这些序列的初始状态一致的情况下,所以每次交换后,要还原,确保初始状态一致。

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

闽ICP备14008679号