全排列算法
方法一:加与不加
思想:每次考虑当前元素时,面临两个选择,即加入子集或者不加入子集,如图所示:
看了图片之后便可对此一目了然
代码如下:
package 递归;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class 求所有子集 {
public static Set<Set<Integer>> all(int[] a, int k) {
Set<Set<Integer>> res_new = new HashSet<Set<Integer>>();// 创建一个新的集合
if (k == 0) {
Set<Integer> nul = new HashSet<Integer>();
Set<Integer> first = new HashSet<Integer>();
first.add(a[0]);
res_new.add(nul);
res_new.add(first);
return res_new;
}
Set<Set<Integer>> res_old = all(a, k - 1);// 前面已经弄好的集合
for (Set<Integer> set : res_old) {
res_new.add(set);// 对于当前处理的第k个元素,无非两种情况,加进集合或者不加进集合,这里是不加当前元素的情况
Set<Integer> su = (Set<Integer>) ((HashSet) set).clone();
su.add(a[k]);
res_new.add(su);// 这里是考虑要加入当前元素的情况,但是一定要注意必须对以前的元素进行克隆,如果不进行克隆,会改变以前的元素
}
return res_new;
}
public static void main(String[] args) {
int[] a = { 1, 23, 2, 3 };
for (int s : a) {
System.out.print(s + " ");
}
System.out.println("求解这个数组的所有子集");
Set<Set<Integer>> sub = all(a, a.length - 1);
Iterator it = sub.iterator();
while (it.hasNext()) {
Set<Integer> o = (Set<Integer>) it.next();
if (o.isEmpty()) {
it.remove();
}
}
System.out.println(sub);
System.out.println("子集的数量为" + sub.size());
}
}
运行结果如图所示:
方法二:交换元素
思想:当前元素与后面每个元素这个进行交换,然后下一个元素也是如此进行递归,但是要注意的是递归之后一定要进行回溯
代码如下:
package 全排列;
public class 全排列算法 {
public static void swap(int[] a, int m, int n) {
int t;
t = a[m];
a[m] = a[n];
a[n] = t;
}
public static void f(int[] a, int k) {
if (k == a.length) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
System.out.println();
}
for (int i = k; i < a.length; i++) {
swap(a, i, k);
f(a, k + 1);
swap(a, i, k);
}
}
public static void main(String[] args) {
int[] a = { 1, 2, 4, 3, 6 };
f(a, 0);
}
}