生成1-n的全排列,算法是递归枚举解答树。
1 void permutation(final int n, int[] path, int cur) {
2 if (cur == n) {
3 System.out.println(Arrays.toString(path));
4 return;
5 }
6 for (int i = 1; i <= n; i++) {
7 boolean isOK = true;
8 for (int j = 0; j < cur; j++) {
9 if (i == path[j]) {
10 isOK = false;
11 break;
12 }
13 }
14 if (isOK) {
15 path[cur] = i;
16 permutation(n, path, cur + 1);
17 }
18 }
19 }
除了用数组path记录路径,还可以使用其他数据结构。
1 void permutation(final int n, Stack<Integer> path, int cur) {
2 if (cur == n) {
3 System.out.println(path);
4 return;
5 }
6 for (int i = 1; i <= n; i++) {
7 if (!path.contains(i)) {
8 path.push(i);
9 permutation(n, path, cur + 1);
10 path.pop(); // comments
11 }
12 }
13 }
看起来简洁了不少,但是注意有注释的哪一行,修改全局变量,必须改成原来的状态。要仔细体会数组和Collection的区别。
现在深化这个题目,生成一个整型数组中的数字的全排列。
值得警惕的是,数组中可能还有重复元素,这需要我们不重不漏地把排列打印出来。
先把int[] x 排序,然后调用下面的方法。
1 void permutation(int[] x, int[] path, int cur) {
2 if (cur == x.length) {
3 System.out.println(Arrays.toString(path));
4 return;
5 }
6 for (int i = 0; i < x.length; i++) {
7 if (i > 0 && x[i] == x[i - 1]) {
8 continue;
9 }
10 int c1 = 0, c2 = 0;
11 for (int j = 0; j < cur; j++) {
12 if (x[i] == path[j]) c1++;
13 }
14 for (int j = 0; j < x.length; j++) {
15 if (x[i] == x[j]) c2++;
16 }
17 if (c1 < c2) {
18 path[cur] = x[i];
19 permutation(x, path, cur + 1);
20 }
21 }
22 }
参考:《算法竞赛入门经典》