Java求全排列(字典序和递归)

文章主体转载自 https://www.cnblogs.com/zhouthanos/p/3807495.html

\tiny 文章主体转载自https://www.cnblogs.com/zhouthanos/p/3807495.html\small 啊示例: 1 2 3的全排列如下:

1 2 3 , 1 3 2 , 2 1 3 , 2 3 1 , 3 1 2 , 3 2 1

方法一、字典序

如果当前排列是124653,找它的下一个排列的方法是,从这个序列中从右至左找第一个左邻小于右邻的数

如果找不到,则所有排列求解完成,如果找得到则说明排列未完成。

本例中将找到46,计4所在的位置为i,找到后不能直接将46位置互换,而又要从右到左到第一个比4大的数

本例找到的数是5,其位置计为j,将i与j所在元素交换125643,

然后将i+1至最后一个元素从小到大排序得到125346,这就是124653的下一个排列。

下图是用字典序法找1 2 3的全排列(全过程):

import java.util.Arrays;

public class Main {

	public static void main(String[] arg) {
		String s = "123";
		char[] data = s.toCharArray();
		Prim(data);

	}

	public static void Prim(char[] data) {
		Arrays.sort(data);
		while (nextPermutate(data)) {
			System.out.println(data);
		}

	}

	private static boolean nextPermutate(char[] data) {
		int end = data.length - 1;
		int swapPoint1 = end, swapPoint2 = end;
		// the actual swap-point is swapPoint1 - 1
		while (swapPoint1 > 0 && data[swapPoint1] <= data[swapPoint1 - 1])
			swapPoint1--;
		if (swapPoint1 == 0)
			return false;
		else {
			while (swapPoint2 > 0 && data[swapPoint2] <= data[swapPoint1 - 1])
				swapPoint2--;
			swap(data, swapPoint1 - 1, swapPoint2);
			reverse(data, swapPoint1, end);
			return true;
		}
	}

	private static void swap(char[] data, int left, int right) {
		char temp = data[left];
		data[left] = data[right];
		data[right] = temp;
	}

	private static void reverse(char[] data, int left, int right) {
		for (int i = left, j = right; i < j; i++, j--)
			swap(data, i, j);
	}

}

方法二、递归

于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。


换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。

public class RecursionPermutation {

    public static void permutate(String input){
        if(input == null)
            throw new IllegalArgumentException();
        char[] data = input.toCharArray();
        permutate(data, 0);
    }
    
    public static void permutate(char[] data, int begin){
        int length = data.length;
        if(begin == length)
            System.out.println(data);
        for(int i = begin ; i < length; i++)
        {
            if(isUnique(data, begin, i)){
                swap(data, begin, i);
                permutate(data, begin + 1);
                swap(data, begin, i);
            }                
        }
    }
    
    private static boolean isUnique(char[] data, int begin, int end){
        for(int i = begin; i < end; i++)
            if(data[i] == data[end])
                return false;
        return true;
    }
    
    private static void swap(char[] data, int left, int right) {
        char temp = data[left];
        data[left] = data[right];
        data[right] = temp;
    }
    
    
    public static void main(String... args){
        RecursionPermutation.permutate("aac");
    }

}

猜你喜欢

转载自blog.csdn.net/Broken_Wave/article/details/82317515