全排列
来源:互联网 发布: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)中找不到相邻并且递增的两个数}
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- 全排列
- C#中的自定义控件
- 数据流DataInput(Output)Stream 和 字节数组流 ByteArrayInput(Output) Stream
- 关于郭天祥51开发板无法烧写程序问题的解决(Prolific USB-to-Serial Comm Port)
- cocos2dx 加减速
- android图形界面UI详解
- 全排列
- keepalived主备切换后虚拟IP漂移慢的解决方法
- cocos2dx lua 灵活使用table类
- java 加入一个线程、创建有响应的用户界面 。 示例代码
- FPGA机器学习之stanford机器学习第九堂
- 用cx_Freeze把python打包成exe可执行文件
- 通过CSS进行SEO优化
- Source Insight 项目简单使用说明
- LeetCode之Decode Ways