不得不说,C++的next_Permutation十分好用,自然而然,我想找找Java里有没有类似的函数。嗯,没找到。不过没关系,我们可以用Java自己实现一个。
如果我们将全排列按照大小顺序进行排序,假设我们知道了第i个排列是[A0, A1, A2, A3, ……],那么第i+1个排列就是比[A0,A1, A2, A3, ……]大,且最小的那个。找到i+1个排列的步骤如下
1)从后往前两两比较,找到第一个满足a[i]<a[i+1]的两个元素
2)从a[i+1]开始往后找,找到一个大于a[i]中最小的一个元素,这个元素的下标记为j,交换a[i]和a[j]
3)将[i+1, a.length-1]的元素全部逆序
public class Exam {
public static void main(String[] args) {
//测试
int n[] = {1,1,3,4};
do {
for (int i:n)
System.out.print(i+" ");
System.out.println();
}while(nextPermutation(n));
}
private static boolean nextPermutation(int[] array){
boolean hasNext = false;
int i;
for(i = array.length-2; i >= 0; i--){
if(array[i] < array[i+1]){
hasNext = true;
break;
}
}
if(!hasNext){//如果所有元素是从大到小排列,说明是最大的字符串
return false;
}
//从i+1的下标往后找(必定是单调递减),在大于array[i]的集合中找一个最小的元素
int j;
for(j = i+1; j < array.length; j++){
if(array[j] <= array[i]){
break;
}
}
j--;
//交换这两个元素,然后逆序i+1及以后的所有元素 [i+1,array.length)
swap(array, i, j);
reverse(array, i+1, array.length);
return true;
}
private static void swap(int[] array, int i, int j) {
int temp =array[i];
array[i] = array[j];
array[j] =temp;
}
private static void reverse(int[] array, int start, int end){
for(int i = start, j = end-1; i < j; i++, j--) {
swap(array, i, j);
}
}
}
输出:
1 1 3 4
1 1 4 3
1 3 1 4
1 3 4 1
1 4 1 3
1 4 3 1
3 1 1 4
3 1 4 1
3 4 1 1
4 1 1 3
4 1 3 1
4 3 1 1
(了解更多:深度优先搜索实现有重复元素的全排列(Java实现))