枚举排列

生成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 }

参考:《算法竞赛入门经典》

猜你喜欢

转载自www.cnblogs.com/wmzhang/p/9226398.html