全排列

来源:互联网 发布:p2p网络借贷法律规定 编辑:程序博客网 时间:2024/04/30 22:02

OJ突然打不开了,下次把题目补上。

一开始看到题目,觉得是到简单题,用回溯法就解决了。然后,WA了无数次...

再次认真审题发现,输出结果是


1 2 3                          而不是      1 2 3

1 3 2                                            1 3 2

2 1 3                                            2 1 3

2 3 1                                            2 3 1

3 1 2                                            3 2 1

3 2 1                                            3 1 2


发现了问题就该改,但是从回溯中没想到改怎么改,在网上搜到了另一种方法——全排列的非递归算法,问题就解决了。

下面贴代码:

回溯法:

<pre name="code" class="cpp">void Perm(int *a,int k,int n){     if(k==n-1)     {        for(int i=0;i<n;i++)        {           cout<<a[i];           if(i!=n-1)           {              cout<<" ";           }        }        cout<<endl;     }     else     {         for(int i=k;i<n;i++)          {              int t=a[k];a[k]=a[i];a[i]=t;          //改变元素位置              Perm(a,k+1,n);              t=a[k];a[k]=a[i];a[i]=t;              //将改变过的位置还原           }     }}


递归算法通过选择元素,改变位置,达到组成所有排列的结果。
(递归的代码好写一点,也容易理解)


接下来,非递归算法

非递归算法是通过不断找下一个排列,直到找不到下一个排列就停止。(那什么时候找不到下一个排列?比如(3,1,2)的下一个是(3,2,1),而(3,2,1)就是最后一个。

不再有下一个,就这样不好理解,看代码。

(注:找下一个排列的方法,如(3,1,2),先从后向前找到序列中两个相邻并且递增的数,如(1,2),其中小得那个数(1)叫做替换数,它的下标叫做替换点。

然后从替换点向后找一个比替换数大的最小数(一定存在),把这个数和替换数交换,再将替换点后的所有数颠倒,得到的就是下一个排列(字典序)。)

例子:

(2,3,1,4) 先从最后向前找到递增且相邻的两个数1,4;再从1的后面找一个大于1的数,只有4,那么交换,得到(2,3,4,1),然后4以后的数颠倒,还是得到(2,3,4,1)

再找一个;从后向前找到递增且相邻的两个数3,4,;再从3后面找大于3的数,只有4,那么交换,得到(2,4,3,1),然后4以后的数颠倒,得到(2,4,1,3)

代码:

<pre name="code" class="cpp">bool Next_Permutation(int *a,int n){     int i,t,k=n-1;     while(k>0)     {          if(a[0]==a[k])   //排除重复元素造成的干扰          {             k--;continue;          }          t=k;          k--;          if(a[k]<a[t])              //找到递增并且相邻的两个数          {               int f=n-1;               for(;f>t;f--)        //在替换点以后找一个大于替换数的最小的数               {                   if(a[f]<a[t]&&a[f]>a[k])                    {break;}               }               int temp=a[f];a[f]=a[k];a[k]=temp;   //与替换数交换               int p=t,q=n-1;               while(p<=q)                            //电脑替换点以后的所有数               {                    temp=a[p];a[p]=a[q];a[q]=temp;               }          }          return true;     }     return false;                              // 这就是最后找不到下一个排列,因为(4,3,2,1)中找不到相邻并且递增的两个数}


0 0
原创粉丝点击