两个经典递归模板,以前写过,现在再过一遍!
基本思路:
如果题目给的输入时数组,首先先要把数组转为ArrayList,因为ArrayList可以很方便地插入,删除,添加!
其次,递归函数的形式都一样,一共有3个参数,分别叫ArrayList<Integer> done, ArrayList<Integer> rest, ArrayList<ArrayList<Integer>> ret 。 done存放已经处理过的数据,rest存放还没处理的数据,ret存放最后的结果。注意这里的Integer可以是泛型,任意的data type。
具体思路:
全排列:对A[0,1,2,3...n] 每次依次取一个元素,添加到done里,然后对剩下的rest递归,直到rest为空。所以总的结构就是一个for循环里面,有一个从rest取数据,递归,撤销的过程。所以总结一下就是,每次递归,轮流从rest里取数据,依次添加到done。
子集:每次取出rest的第一个元素,然后做决定是否添加到done里面,可以添加,也可以不添加,所以会有两个递归。所以总结一下就是,每次递归,总是取rest的第一个数据,然后做两种选择。
import java.util.*;
public class HelloWorld{
public static void main(String []args){
int[] A = {1,2,3};
subset(A);
permutation(A);
String s = "abc";
permutationStringRec(new StringBuilder(), new StringBuilder(s));
}
// ======================================================= permutation
public static void permutation(int[] A) {
ArrayList<Integer> rest = new ArrayList<Integer>();
ArrayList<Integer> done = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
for(int i : A) {
rest.add(i);
}
permutationRec(done, rest, ret);
System.out.println(ret);
}
public static void permutationRec(ArrayList<Integer> done, ArrayList<Integer> rest, ArrayList<ArrayList<Integer>> ret) {
if(rest.size() == 0) {
ret.add(new ArrayList<Integer>(done));
return;
}
for(int i=0; i<rest.size(); i++) {
int val = rest.get(i); // 选择第i个元素,添加到done
done.add(val);
rest.remove(i);
permutationRec(done, rest, ret);
rest.add(i, val);
done.remove(done.size()-1);
}
}
// ======================================================= subset
public static void subset(int[] A) {
ArrayList<Integer> rest = new ArrayList<Integer>();
ArrayList<Integer> done = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
for(int i : A) {
rest.add(i);
}
subsetRec(done, rest, ret);
System.out.println(ret);
}
public static void subsetRec(ArrayList<Integer> done, ArrayList<Integer> rest, ArrayList<ArrayList<Integer>> ret) {
if(rest.size() == 0) {
ret.add(new ArrayList<Integer>(done));
return;
}
int first = rest.remove(0);
// 选择添加到done
done.add(first);
subsetRec(done, rest, ret);
done.remove(done.size()-1);
// 选择不添加到done
subsetRec(done, rest, ret);
rest.add(0, first);
}
// ======================================== permutationStringRec 另一种用StringBuilder的变型版
public static void permutationStringRec(StringBuilder done, StringBuilder rest){
if(rest.length() == 0) {
System.out.println(done.toString());
return;
}
for(int i=0; i<rest.length(); i++) {
char c = rest.charAt(i);
done.append(c);
rest.deleteCharAt(i);
permutationStringRec(done, rest);
rest.insert(i, c);
done.deleteCharAt(done.length()-1);
}
}
}