全排列的几种算法

全排列,我们高中时就学过,数学上很简单,可是用计算机的算法实现还是有点味道的,

今天我将我碰到的几种算法如数奉上,欢迎交流!

第一种:递归

最常见的也是最好理解的方法:

简单点:比如"a" ,"b","c"全排列,可以看做事"a" +"b","c"的全排列 及"b"+ "a","c"的全排列 及"c" +  "a","b"的全排列

也就是说,遍历原数组中的每个元素,让剩余的元素全排列,这样就找到规律了。

代码如下:

public static void main(String[] args) {
        char buf[]={‘a‘,‘b‘,‘c‘,‘d‘};
        perm(buf,0,buf.length-1);
    }
    public static void perm(char[] buf,int start,int end){
        if(start==end){//当只要求对数组中一个字母进行全排列时,只要就按该数组输出即可(特殊情况)
            for(int i=0;i<=end;i++){
                System.out.print(buf[i]);
            }
            System.out.println();
        }
        else{//多个字母全排列(普遍情况)
            for(int i=start;i<=end;i++){//(让指针start分别指向每一个数)
                char temp=buf[start];//交换数组第一个元素与后续的元素
                buf[start]=buf[i];
                buf[i]=temp;  

                perm(buf,start+1,end);//后续元素递归全排列  

                temp=buf[start];//将交换后的数组还原
                buf[start]=buf[i];
                buf[i]=temp;
            }
        }
    }  

第二中方法:也是递归,

但是和第一种有所区别,

算法:将数据分为两部分,递归将数据从左侧移右侧实现全排列

比较抽象,

如list abcd,遍历每一个数,将每个数放到一个新的list中,并将该元素从原list删除,然后将剩下的元素继续遍历每个元素继续放到新的list里,这样,当list的长度为原list长度,或者原list长度为0时打印结果!

下面是简单的示意图:

// abcd
            //bcd  a
                    //cd ab
                            //d abc
                                    //abcd
                            //c abd
                                    //abdc
                    //bd ac
                            //d acb
                                    //acbd
                            //b acd
                                    //acdb
                    //bc ad    ...

            //acd  b      ...
            //abd  c      ...
            //abc  d      ...

源代码如下:

 private static void sort(List datas, List target) {
        //System.out.println("size="+datas.size());
        if (datas.size()==0) {
            for (Object obj : target)
                System.out.print(obj+" ");
            System.out.print(" ");
            return;
        }
        for (int i = 0; i < datas.size(); i++) {
            List newDatas = new ArrayList(datas);
            List newTarget = new ArrayList(target);
            newTarget.add(newDatas.get(i));
            newDatas.remove(i);
            sort(newDatas, newTarget);
        }
    }
    public static void main(String[] args) {
        List list = new ArrayList();
        for(int i=0;i<5;i++){
            list.add(i+1);
        }
        sort(list, new ArrayList());
    }  

第三种方法:非递归

直接上代码:

public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6};
        for(int i :arr){
            System.out.print(i + " ");
        }
        System.out.println();
        int totalnum = 1;
        while(NextNumber(arr,arr.length)){
            for(int i :arr){
                System.out.print(i + " ");
            }
            System.out.println();
            totalnum ++;
        }
        System.out.println("Total Num: " + totalnum);
    }
    private static Boolean NextNumber(int[] arr, int n){
        //数组最后一个元素位置
        int lastIndex = n-1;
        //从右向左确定第一个数字(前面的数字比它小)
        int firstIndex = lastIndex;
        for(;arr[firstIndex-1]>arr[firstIndex];firstIndex--){
            if(firstIndex == 1){
                //已经轮询完毕,此数已经是最大的那个数
                return false;
            }
        }
        //从右向左确定一个交换数(此数比arr[firstIndex]小且比arr[firstIndex-1]大)
        int swapIndex = lastIndex;
        for(;swapIndex > firstIndex;swapIndex--){
            if(arr[swapIndex] < arr[firstIndex] && arr[swapIndex] > arr[firstIndex-1]){
                break;
            }
        }
        //交换数字
        swap(arr,firstIndex-1,swapIndex);
        //将firstIndex右边的数字排序
        for(;firstIndex < lastIndex;firstIndex++,lastIndex--){
            if(arr[firstIndex] > arr[lastIndex]){
                swap(arr,firstIndex,lastIndex);
            }
        }
        return true;
    }
    private static void swap(int[] arr,int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

如果此文对你有帮助,请留个言,新人需要打架的支持和鼓励!

全排列的几种算法

时间: 2024-10-12 16:05:26

全排列的几种算法的相关文章

最近公共祖先(三种算法)

最近研究了一下最近公共祖先算法,根据效率和实现方式不同可以分为基本算法.在线算法和离线算法.下面将结合hihocoder上的题目分别讲解这三种算法. 1.基本算法 对于最近公共祖先问题,最容易想到的算法就是从根开始遍历到两个查询的节点,然后记录下这两条路径,两条路径中距离根节点最远的节点就是所要求的公共祖先. 题目参见 #1062 : 最近公共祖先·一 附上AC代码,由于记录的方式采取的是儿子对应父亲,所以实现的时候有点小技巧,就是对第一个节点的路径进行标记,查找第二个节点的路径时一旦发现访问到

客户端负载均衡Ribbon之二:Loadbalance的几种算法以及在ribbon中的使用

Load Balance负载均衡是用于解决一台机器(一个进程)无法解决所有请求而产生的一种算法. 像nginx可以使用负载均衡分配流量,ribbon为客户端提供负载均衡,dubbo服务调用里的负载均衡等等,很多地方都使用到了负载均衡. 使用负载均衡带来的好处很明显: 当集群里的1台或者多台服务器down的时候,剩余的没有down的服务器可以保证服务的继续使用 使用了更多的机器保证了机器的良性使用,不会由于某一高峰时刻导致系统cpu急剧上升 负载均衡有好几种实现策略,常见的有: 随机 (Rando

hdu 1162 Eddy&#39;s picture 最小生成树入门题 Prim+Kruskal两种算法AC

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7428    Accepted Submission(s): 3770 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to

Opencv——彩色图像灰度化的三种算法

为了加快处理速度在图像处理算法中,往往需要把彩色图像转换为灰度图像.24为彩色图像每个像素用3个字节表示,每个字节对应着RGB分量的亮度. 当RGB分量值不同时,表现为彩色图像:当RGB分量相同时,变现为灰度图像: 一般来说,转换公式有3中. (1)Gray(i,j)=[R(i,j)+G(i,j)+B(i,j)]/3; (2)Gray(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.144*B(i,j); (3)Gray(i,j)=G(i,j);//从2可以看出G的分量比较大所

Java利用 DES / 3DES / AES 这三种算法分别实现 对称加密

转载请注明出处:http://blog.csdn.net/smartbetter/article/details/54017759 有两句话是这么说的: 1)算法和数据结构就是编程的一个重要部分,你若失掉了算法和数据结构,你就把一切都失掉了. 2)编程就是算法和数据结构,算法和数据结构是编程的灵魂. 注意,这可不是我说的,是无数程序员总结的,话说的很实在也很精辟,若想长久可持续发展,多研究算法还是很有必要的,今天我给大家说说加密算法中的对称加密算法,并且这里将教会大家对称加密算法的编程使用.包含

快速排序、归并排序、堆排序三种算法性能比较

快速排序.归并排序.堆排序三种排序算法的性能谁最好呢?网上查了一下说快速排序最快.其次是归并排序,最差的是堆排序:而理论上三种排序算法的时间复杂度都是O(nlogn),只不过快速排序最差的会达到O(n^2),但是数据的随机性会消除这一影响,今天就来实际比较一下: 1 #include <iostream> 2 #include<time.h> 3 using namespace std; 4 #define MAX 100000000 5 int data1[MAX],data2[

次小生成树的两种算法

一."换边"算法 用Kruskal求最小生成树,标记用过的边.求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就是次小的生成树.可以证明:最小生成树与次小生成树之间仅有一条边不同. 这样相当于运行m次Kruskal算法. 复杂度O(m^2) 示例代码: int Kruskal_MinTree() { int u,v; init(); int i,flag,cnt; minedge = 0; flag = cnt = 0; int tmp = 0;

最小生成树的两种算法:Prim和Kruskal算法

越来越明白了一个道理:你写不出代码的原因只有一个,那就是你没有彻底理解这个算法的思想!! 以前写过最小生成树,但是,水了几道题后,过了一段时间,就会忘却,一点也写不出来了.也许原因只有一个,那就是我没有彻底理解这两种算法. 主题: 其实,求最小生成树有两个要点,一个是权值最小,还有一个就是这个图必须是树.而Prim和Kruskal的不同之处在于两者选择的变量不同,Prim选择的是始终保持权值最小,然后逐个加点构建一棵树.而Kruskal则是始终保证是一棵树(虽然构建过程中不一定是真正的树,但并查

重拾算法(5)——最小生成树的两种算法及其对比测试

重拾算法(5)——最小生成树的两种算法及其对比测试 什么是最小生成树 求解最小生成树(Minimum Cost Spanning Tree,以下简写做MST)是图相关的算法中常见的一个,用于解决类似如下的问题: 假设要在N个城市之间建立通信联络网,那么连通N个城市只需N-1条线路.这时自然会考虑这样一个问题:如何在最节省经费的前提下建立这个通信网. 在任意两个城市间都可以设置一条线路,相应地都要付出一定的经济代价.N个城市之间最多可能设置N(N-1)/2条线路,那么如何在这些线路中选择N-1条,