想到 前几天的一个问题,如何实现元素的全排列 并且按照升序输出。
可以有两种方法:递归和非递归
首先介绍非递归的方法:
思路:
以三个数字为例1,2,3升序的全排列为:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
显然每个组合 都有一个直接后继,找到一个数没有后继如 3 2 1 则停止。
问题来了 那就是如何找到后继和没有后继的数如何判断该数是否有后继。就是对于一个数,如何找到一个比它大的,且最小的数.
还是1 2 3为例 ,假设 此时的排列为"1 3 2" ,那么32是非递增的,而13是递增的,满足要求,然后根据要求2是比1大的最小的数,此时交换两个数的位置得到2 3 1 ,此时 把交换位置后面的数字颠倒反转即可。得到2 1 3 ,后面的排列都需要这么做,直到碰到3 2 1即可。
代码如下
1: public class NonRecursivePermutation {
2:
3: static int[] arr = new int[] { 1, 2, 3, 4, 5, 6 };
4: static int count = 1;
5:
6: // 反转区间
7: private static void reverse(int[] arr, int pBegin, int pEnd) {
8: while (pBegin < pEnd)
9: swap(arr, pBegin++, pEnd--);
10: }
11:
12: private static void swap(int[] arr, int i, int j) {
13: int temp;
14: temp = arr[i];
15: arr[i] = arr[j];
16: arr[j] = temp;
17: }
18:
19: private static boolean hasNext() {
20: for (int i = arr.length - 1; i > 0; i--) {
21: if (arr[i] > arr[i - 1])
22: return true;
23: }
24: return false;
25: }
26:
27: private static void next() {
28: int len = arr.length;
29: int replace = 0; // 需替换数
30: int firstR = 0; // 从后向前找比替换数大的第一个数
31: // 找降序的相邻2数,前一个数即需替换数
32: for (int i = len - 1; i > 0; i--) {
33: if (arr[i] > arr[i - 1]) {
34: replace = i - 1;
35: break;
36: }
37: }
38:
39: //System.out.println("需替换数位置:" + replace);
40:
41: // 从后向前找比替换数大的第一个数
42: // 比如926540的后继应该是946520,而不是956240
43: for (int i = len - 1; i > replace; i--) {
44: if (arr[i] > arr[replace]) {
45: firstR = i;
46: break; //找到之后直接退出
47: }
48: }
49:
50: //System.out.println("替换数位置:" + firstR);
51:
52: // replace与firstR交换
53: swap(arr, replace, firstR);
54: // 替换数后的数全部反转
55: reverse(arr, replace + 1, len - 1);
56:
57: count++;
58: print();
59: }
60:
61: private static void print() {
62: for (int i = 0; i < arr.length; i++)
63: System.out.print(arr[i] + " ");
64: System.out.println();
65: }
66:
67: /**
68: * @param args
69: */
70: public static void main(String[] args) {
71:
72: while (hasNext() == true) {
73: next();
74: }
75: System.out.println("数组完全反转后的结果:");
76: reverse(arr, 0, arr.length - 1);
77: print();
78: System.out.println("全排列的数目为:" + count);
79:
80: /*********************/
81: System.out.println("数组是否存在后继:" + hasNext());
82: System.out.println("数组一次替换后的结果:");
83: next();
84: }
85:
}
代码的核心部分是在next和hasNext函数中。
(下篇文章介绍递归的方法)