免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 7868 | 回复: 32
打印 上一主题 下一主题

[算法] 如何用非递归的算法来求解一个"全排列" [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-02 15:28 |只看该作者 |倒序浏览
求一个数列的全排列,用递归的方法很容易描述,网上也有很多例子

但是如果要求必须不能用递归,可以用堆栈来求解,这个算法/代码应该如何描述呢? 我在纸上试了一下,没出来。

大家有什么思路么?

论坛徽章:
0
2 [报告]
发表于 2012-09-02 15:31 |只看该作者
很容易啊,求一个排列的下一个排列是O(n)的算法。
很排好序,当作第一个排列,然后一直求下一个排序,直接没有下一个即可。

论坛徽章:
0
3 [报告]
发表于 2012-09-02 19:09 |只看该作者
_Rayx 发表于 2012-09-02 15:31
很容易啊,求一个排列的下一个排列是O(n)的算法。
很排好序,当作第一个排列,然后一直求下一个排序,直 ...


能否稍微详细一点呢? 我想展开这个思路发现还是卡住了。

论坛徽章:
0
4 [报告]
发表于 2012-09-02 19:23 |只看该作者
回复 3# weichuang02

关键字
lexicographic permutation 或者 next permutation


   

论坛徽章:
0
5 [报告]
发表于 2012-09-02 19:28 |只看该作者
回复 3# weichuang02


    假设中间某一个排列是 1 3 4 5 9 7 2
它的下一个排列是1 3 4 7 2 5 9
其实就是发现2《7 7<9 9>5,于是找到比5大的最小数,7,交换变成1 3 4 7 9 5 2,再将7后面的数首尾交换,变成1 3 4 7 2 5 9
这样就是下一个排列了。

论坛徽章:
0
6 [报告]
发表于 2012-09-02 21:05 |只看该作者
回复 5# _Rayx

假设中间某一个排列是 1 3 4 5 9 7 2
它的下一个排列是1 3 4 7 2 5 9
其实就是发现2《7 7<9 9>5,于是找到比5大的最小数,7,交换变成1 3 4 7 9 5 2,再将7后面的数首尾交换,变成1 3 4 7 2 5 9
这样就是下一个排列了。


这例子后半组正好3个数字,会让人误解的...
准确地说应该是reverse。
   

论坛徽章:
0
7 [报告]
发表于 2012-09-02 21:25 |只看该作者
本帖最后由 KanonInD 于 2012-09-02 21:26 编辑

lexicographic permutation 用Python写的:http://en.wikipedia.org/wiki/Per ... lexicographic_order
  1. def permutation(ls):
  2.     length = len(ls)
  3.     print(ls)
  4.     while True:
  5.         k = -1
  6.         for i in range(length-1):
  7.             if ls[i] < ls[i+1]:
  8.                 k = i
  9.         if k == -1:break
  10.         l = 0
  11.         for i in range(k,length):
  12.             if ls[k] < ls[i]:
  13.                 l = i
  14.         ls[k],ls[l] = ls[l],ls[k]
  15.         ls[k+1:] = ls[k+1:][::-1]
  16.         print(ls)
复制代码

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
8 [报告]
发表于 2012-09-02 22:16 |只看该作者

论坛徽章:
0
9 [报告]
发表于 2012-09-03 07:52 |只看该作者
回复 6# sacry


    you are right.

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
10 [报告]
发表于 2012-09-18 16:44 |只看该作者
weichuang02 发表于 2012-09-02 15:28
求一个数列的全排列,用递归的方法很容易描述,网上也有很多例子

但是如果要求必须不能用递归,可以用堆 ...

正好之前写了个

  1. #include <stdio.h>

  2. #include <stdlib.h>

  3. int *flag;

  4. void print(int*a,int num)

  5. {

  6.         int i;

  7.         num--;

  8.         for(i=0;i<num;i++)

  9.                 printf("%d->",a[i]);

  10.         printf("%d\n",a[num]);

  11. }



  12. int next(int*a,int m, int n,int how)

  13. {

  14.         int i,j,k,x;

  15.         if(how) {

  16.                 for(j=n-1;j>=0;j--) {

  17.                         for(i=a[j];i<m;i++)

  18.                                 if(flag[i]==0)

  19.                                         break;

  20.                         if(i<m) {

  21.                                 flag[a[j]-1]=0;

  22.                                 a[j]=i+1;

  23.                                 flag[i]=1;



  24.                                 for(x=0,k=j+1;k<n;k++) {

  25.                                         while(flag[x]==1)x++;

  26.                                         a[k]=x+1;

  27.                                         flag[x]=1;

  28.                                 }

  29.                                 return 0;

  30.                         }

  31.                         flag[a[j]-1]=0;

  32.                 }

  33.         }

  34.         else {

  35.                 if(a[n-1]<m) {

  36.                         a[n-1]++;

  37.                         return 0;

  38.                 }

  39.                 for(i=n-1;i>0;i--)

  40.                         if(a[i]>a[i-1]+1)

  41.                                 break;

  42.                 if(i>0) {

  43.                         a[i-1]++;

  44.                         for(;i<n;i++)

  45.                                 a[i]=a[i-1]+1;

  46.                         return 0;

  47.                 }

  48.         }

  49.         return 1;

  50. }



  51. int main(int argc,char**argv)

  52. {

  53.         int *a,i;

  54.         char c;

  55.         int m,n;

  56.         int how=0;

  57.         c=argv[3][0];

  58.         sscanf(argv[1],"%d",&m);

  59.         sscanf(argv[2],"%d",&n);

  60.         if(!(0<n&&n<=m)||(c!='P'&&c!='p'&&c!='C'&&c!='c'))

  61.                 return 1;

  62.         a = malloc(sizeof(int)*n);

  63.         if(c=='P'||c=='p') {

  64.                 how =1;

  65.                 flag = malloc(sizeof(int)*m);

  66.                 for(i=0;i<n;i++)

  67.                         flag[i]=1;

  68.                 for(;i<m;i++)

  69.                         flag[i]=0;

  70.         }

  71.         if(a==NULL)

  72.                 return 1;

  73.         for(i=0;i<n;i++)

  74.                 a[i]=i+1;

  75.         while(1) {

  76.                 print(a,n);

  77.                 if(next(a,m,n,how))

  78.                         return 0;

  79.         }

  80. }

复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP