生成所有全排列 非递归和递归实现

Given a collection of numbers, return all possible permutations.

For example, 元素可以是重复也可以不重复,不一定有序

[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].

 [1,1,2] have the following unique permutations:

[1,1,2][1,2,1], and [2,1,1].

如何计算字符串的下一个排列了?先让数组升序,考虑程序运行中的一种情况。来考虑"926520"这个字符串,我们从后向前找第一双相邻的递增数字,"20"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后面找一个比替换数大的最小数(这个数必然存在),0、2都不行,5可以,将5和2交换得到"956220",然后再将替换点后的字符串"6220"颠倒即得到"950226"    [引言from http://blog.csdn.net/morewindows/article/details/7370155]

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        int array[] = {5,5,3,4};
        System.out.println(new Main().permute(array));
    }
    
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        if(num == null || num.length == 0) {
            return result;
        }
        sort(num);
        do {
            ArrayList<Integer> temp = new ArrayList<Integer>();
            for(int at:num) {
                temp.add(at);
            }
            result.add(temp);
        } while(nextPermute(num));
        return result;
        
    }
    //根据规则计算下个全排列情况
    boolean nextPermute(int[] num) {
        if(num == null || num.length == 1) {
            return false;
        }
        int size = num.length;
        for(int i=num.length-2;i>=0;i--) {
            if(num[i] < num[i+1]) {
                for(int j=num.length-1;j>i;j--) {
                    if(num[j] > num[i]) {
                        int temp = num[i];
                        num[i] = num[j];
                        num[j] = temp;
                        reverse(num,i+1);
                        return true;
                    }
                    
                }
            }
        }
        reverse(num,0);
        return false;
    }
  //把p之后的元素倒序
void reverse(int[] num, int p) { int size = num.length; for(int i=p,j=1;i<size-j;j++,i++) { int temp = num[i]; num[i] = num[size-j]; num[size-j] = temp; } }
  //写个简单的冒泡排序
void sort(int[] num) { int size = num.length; for(int i=0;i<size;i++) { for(int j=0;j<size-i-1;j++) { if(num[j]>num[j+1]) { int temp = num[j]; num[j] = num[j+1]; num[j+1] = temp; } } } } }

 

 

递归实现思路:全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        int array[] = {1,2,3,4,5,6};
        ArrayList<ArrayList<Integer>> result =  new ArrayList<ArrayList<Integer>>();
        new Main().AllRange(array,0,result);
        System.out.println(result);
    }
    
    void swap(int[] num, int a, int b) {
        int temp = num[a];
        num[a] = num[b];
        num[b] = temp;
    }
    /**
     * for example 122   has turn to 212, then need not turn to 221
     */
    boolean needSwap(int[] num, int a, int b) {
        for(int i=a;i<b;i++) {
            if(num[b] == num[i]) {
                return false;
            }
        }
        return true;
    }
    void AllRange(int[] num, int k, ArrayList<ArrayList<Integer>> result) {
        int len = num.length-1;
        if(k == len) {
            ArrayList<Integer> temp = new ArrayList<Integer>();
            for(int at:num) {
                temp.add(at);
            }
            result.add(temp);
        } else {
            for(int i=k;i<=len;i++) {
                if(needSwap(num,k,i)) {                    
                    swap(num,k,i);
                    AllRange(num,k+1,result); //deep into recusive                    
                    swap(num,k,i); //don't forget to swap back
                }
                
            }
        }        
    }
}

 

posted @ 2014-01-08 17:28  yanghuahui  阅读(532)  评论(0编辑  收藏  举报