用代码实现全排列
来源:互联网 发布:c语言中数据类型转换 编辑:程序博客网 时间:2024/05/13 13:53
缘由
今天主要是研究编程之美上的24点的题,结果无意中引出了这个问题,也是面试的经典问题。
排列是什么
排列表示把集合中元素的所有按照一定的顺序排列起来。那么从对于一个集合有多少种排列是在高中就学过了的。公式如下:
例如:{1, 2, 3}的全排列为:
123;132;213;231;312;321;
共6个,即3!=3*2*1=6。
代码实现
那么用代码如何实现呢?这就是主要的难点。我想了很久,以为可以让计算机模仿人的行为。大概人的行为就是如下图所示的吧:
首先取一个元素,例如取出了1,那么就还剩下{2, 3}。然后再从剩下的集合中取出一个元素,例如取出2,那么还剩下{3}。以此类推,把所有可能的情况取一遍,就是全排列了。
那如何用代码表示呢?看了代码一步一步解析:
public class Permutation { public static void permutation(char[]ss,int i){ if(ss==null||i<0 ||i>ss.length){ return; } if(i==ss.length){ System.out.println(new String(ss)); }else{ for(int j=i;j<ss.length;j++){ char temp=ss[j]; ss[j]=ss[i]; ss[i]=temp; permutation(ss,i+1); temp=ss[j]; ss[j]=ss[i]; ss[i]=temp; } } } public static void main(String args[]){ char []ss={'a','b','c'}; permutation(ss,0); } }上面的代码,运行可以得到正确的结果。其中核心在于:
for(int j=i;j<ss.length;j++){ char temp=ss[j]; ss[j]=ss[i]; ss[i]=temp; permutation(ss,i+1); temp=ss[j]; ss[j]=ss[i]; ss[i]=temp; }跟着思路来一遍,当第一次来到这个循环的时候,i=0。那么下面i和j的元素的互换其实没有实质的改变。
char temp=ss[j];ss[j]=ss[i]; ss[i]=temp;接着递归执行了
permutation(ss,i+1);这一步意思就是将这个问题化了子问题,那就是本来求abc的排列,现在求bc的排列,而i+1=1,就是固定了前面第一个字符,也就是a。在递归中的排列并不会影响到a,也就是已经确定的字符。
接着代码又将i和j的元素互换了一下。为什么呢?这就是难点所在。但是如果看下一个循环就非常清楚了,当j=2时,那么递归前的互换,将abc中的ab互换,变成了bac,此时,再执行递归,就固定了第一个元素b,而去求ac的排列。同样,当求完了ac的排列之后,permutation()函数返回时又会将bac变回abc,这其实是为了下一个循环做准备,这是因为当abc的下一个循环会让a与c互换,成了cba,再去求ba的全排列。
通过最简单的abc三个数字全排列的解释,应该很容易理解4、5、甚至更多的排列是如何成功运行的。
在整个过程中还有一个要点就是,前面的固定,也就是permutation(ss,i+1);的第二个参数,可以看到for循环内的j的第一个取值是根据i来决定的,所以i这个数的大小就将整个字符序列变为了两个部分。
- 前一部分是这次求排列的过程中不动的部分
- 从i开始的后一部分是这次求排行中会动的部分
参考博客
- 排列-组合的代码实现
- 排列与组合的Java递归实现
0 0
- 用代码实现全排列
- 字符串全排列代码实现
- 全排列java代码实现
- 字符串全排列的C++实现代码
- 用递归实现全排列
- 用递归实现全排列
- 字符串全排列代码
- 全排列递归代码
- 全排列代码
- 全排列代码
- 复制代码 全排列
- 全排列推演+代码
- 代码--C++全排列和子集的实现
- JavaScript实现数组全排列输出的代码
- python标准算法实现数组全排列代码
- 生成全排列----离散数学及其应用伪代码实现
- 全排列的递归实现(java代码)
- 列举全排列的递归算法的java代码实现
- HDOJ 1003 Max Sum
- javascript设计模式
- epoll原理
- Myeclipse报错:Could not open the editor: Invalid thread access
- cocos2d-x学习笔记(18)--游戏打包(windows平台)
- 用代码实现全排列
- js练习之事件切换图片和控制css样式以及指定页面滚动位置
- Oracle基础
- 回去测试不知道能不能用
- linux内核模块和应用程序有什么区别
- poj2253--Frogger
- SharePoint 2010 名言警句 Web部件
- Android画板案例
- 刨根问底:C++中浮点型变量(float, double)的比较问题。