一般组合排列问题都是用递归来解决。
1. 全组合问题Permutations
先固定一个数,把剩下的数继续组合。
递归函数的参数有:数组num[],一个组合list,返回结果lists。
如果num.length==0,则表示遍历结束,则把这个结果add到lists中,return。
从0开始遍历num,将num[i]add到list中,然后重构num[],即删除num[i],对num[]继续递归。
最后为什么要删除list中最后一个元素,因为此时list已经是一个答案,删除最后一个数,继续下一次数字组合。
public ArrayList<ArrayList<Integer>> permute(int[] num) {
ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
generatePermutations(num,list,lists);
return lists;
}
void generatePermutations(int[] num,ArrayList<Integer> list,ArrayList<ArrayList<Integer>> lists){
if(num.length == 0){
lists.add(new ArrayList<Integer>(list));
return;
}
int length = num.length;
for(int i = 0;i<length;i++){
list.add(num[i]);
int[] newnum = new int[length-1];
for(int j = 0;j<length-1;j++){
if(j<i){
newnum[j] = num[j];
}else{
newnum[j] = num[j+1];
}
}
generatePermutations(newnum,list,lists);
list.remove(list.size()-1);
}
}
2.在n个数中取k个数组合问题
与1思路类似,先固定一个数,再在剩下的数中选数。
递归的传入参数有:n,k,start(从start开始遍历剩下的数),lists,list
递归终止的条件是list.size==k。
public ArrayList<ArrayList<Integer>> combine(int n, int k) {
ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
combineHelp(n,k,1,lists,list);
return lists;
}
void combineHelp(int n,int k,int start,ArrayList<ArrayList<Integer>> lists,ArrayList<Integer> list){
if(list.size()==k){
lists.add(new ArrayList<Integer>(list));
return;
}
for(int i=start;i<=n;i++){
list.add(i);
combineHelp(n,k,i+1,lists,list);
list.remove(list.size()-1);
}
}
3.
Letter Combinations of a Phone Number
首先构造一个字符串数组,表示每个数字所代表的字母。
先固定一个数,再把右边剩下的数作为参数,继续递归。
每递归一个数,根据字典里表示的字符串循环构建答案,每次完成递归后,都要remove最后一个字符,以便下一次的构造。
注意:递归结束的条件是dilen == temp.length(),dilen是输入参数的长度,temp是一个结果。不能用digits.length()==0(digits是递归函数中的参数),否则会出错。
public ArrayList<String> letterCombinations(String digits) {
String[] dicts = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
ArrayList<String> list = new ArrayList<String>();
recursive(digits,dicts,"",list,digits.length());
return list;
}
public void recursive(String digits,String[] dicts,String temp,List<String> list,int dilen){
int len = digits.length();
if(dilen == temp.length()){
list.add(temp);
return;
}
String dict = "";
for(int i=0;i<len;i++){
int c = digits.charAt(i)-'0';
dict = dicts[c];
for(int j=0;j<dict.length();j++){
temp += String.valueOf(dict.charAt(j));
recursive(digits.substring(i+1,len),dicts,temp,list,dilen);
temp = temp.substring(0,temp.length()-1);
}
}
}