从n个不一样元素中任取m(m≤n)个元素,按照必定的顺序排列起来,叫作从n个不一样元素中取出m个元素的一个排列。当m=n时全部的排列状况叫全排列。java
n个数(字符、对象)的全排列一共有n!种,因此全排列算法至少时间O(n!)的。若是要对全排列进行输出,那么输出的时间要O(n∗n!),由于每个排列都有n个数据。因此实际上,全排列算法对大型的数据是没法处理的,而通常状况下也不会要求咱们去遍历一个大型数据的全排列。算法
首先,明确一点,本算法使用递归实现的,因此要求对递归有所了解。数组
当咱们要求一组字母的全排列,形如:函数
【A,B,C,D】this
你会怎么作呢?我会这样作:spa
第一步:将【A,B,C,D】将中的任意一个元素取出;.net
第二步:从剩下的三个元素中再任意取出一个元素;code
第三步:从剩下的两个元素中再任意取出一个元素;对象
第四步:取出最后一个元素;blog
这样就能够获得一个【A,B,C,D】排列了!效仿上面的四个步骤,只是不取重复的元素。就能够获得【A,B,C,D】因此的排列了吗?
以此类推,【A】,【A,B】,【A,B,C】,【A,B,C,D,E】,【A,B,C,D,E,...】的全排列也能够一一列出。
到目前为止,细心的你应该能够发现,【A】,【A,B】,【A,B,C】,【A,B,C,D】,【A,B,C,D,E】,【A,B,C,D,E,...】求全排列的方法都是同样的,只是在元素有所差别。因此在写算法时,咱们只要写一个函数来求不一样的全排列。
public class Main { public static void main(String[] args) { DataContainer data = new DataContainer(new Character[]{'a', 'b', 'c', 'd'}); Stack<Object[]> res = new Stack<>(); permu(data, res, new Stack<Object>()); //打印 for(Object[] objs: res){ for(Object o: objs){ System.out.print(o); } System.out.println(); } } /** * 求全排列的函数 * @param data 被排列的数组 * @param res 装载一个排列 * @param objs 装载全部排列 */ static void permu(DataContainer data, Stack<Object[]> res, Stack<Object> objs) { if (data.effectSize == 0) { res.push(objs.toArray()); } for (int i = 0; i < data.actualSize; i++) { if(data.state(i) == true){ objs.add(data.getElement(i)); permu(data, res, objs); //回溯 data.recovery(i); objs.pop(); } } } }
/** * * @author liutaigang * */ class DataContainer { Inner[] inners; int effectSize;// 有效元素的个数 int actualSize;// 实际元素的个数 DataContainer(Object[] data) { int len = data.length; this.actualSize = len; this.effectSize = len; inners = new Inner[len]; for (int i = 0; i < len; i++) { inners[i] = new Inner(data[i], true); } } /** * @param index 索引 * @return 返回inners中指定的有效值,若无效就返回null */ Object getElement(int index){ if(inners[index].state == true){ inners[index].state = false;//取过就无效了 effectSize--; return inners[index].element; } return null; } boolean state(int index){ return inners[index].state; } /** * 将指定的元素恢复为有效状态 * @param index 索引 */ void recovery(int index){ if(inners[index].state == false){ effectSize++; inners[index].state = true; } } /** * 内部类 * @author liutaigang * */ class Inner { Object element;// 元素 boolean state;// 状态:有效——true,无效——false Inner(Object element, boolean state) { this.element = element; this.state = state; } } }
固然,上述只是全排列的一种实现方法,甚至有些繁杂。仅仅是想为你们提供一种思路。还有一些关于全排列的blog,很值得参考:
http://blog.csdn.net/summerxiachen/article/details/60579623
end