题目:
把一个数组里的数的组合全部列出,比如1和2列来为1,2,12,21.
分析:
这道题有多种扩展,
1,没有重复元素的数的组合(包括子集的全排列);
2,有重复元素的数的组合;
3,没有重复元素的数的全排列;
4,有重复元素的数的全排列。
1,没有重复元素的数的组合
思路:将数组元素存在LinkedList里(方便删除),遍历List,删除当前元素并把此元素加入结果,如果结果长度不为0,则输出,以此递归。
package javainterview; import java.util.Arrays; import java.util.LinkedList; import java.util.List; public class Q7_1_1_a { public static void listAll(List<Integer> candidate, String prefix){ if(prefix.length()!=0){ System.out.println(prefix); } for(int i=0; i<candidate.size(); i++){ List<Integer> temp = new LinkedList<Integer>(candidate); int item = (int)temp.remove(i); listAll(temp, prefix+item); } } public static void main(String[] args) { Integer[] array = {1,2}; List<Integer> list = Arrays.asList(array); listAll(list, ""); } }2,有重复元素的数的组合
思路,因为有重复元素,按照1的做法,会出现重复的情况,这里的处理方法是把结果保存在一个HashSet里,每得到一个结果,检查HashSet里是否已经存在,不存在才输出。
package javainterview; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; public class Q7_1_1_b { public static void listAll(List<Integer> candidate, String prefix, HashSet<String> hs){ if(prefix.length()!=0 && !hs.contains(prefix)){ System.out.println(prefix); hs.add(prefix); } for(int i=0; i<candidate.size(); i++){ List<Integer> temp = new LinkedList<Integer>(candidate); int item = (int)temp.remove(i); listAll(temp, prefix+item, hs); } } public static void main(String[] args) { Integer[] array = {1,1,2}; List<Integer> list = Arrays.asList(array); HashSet<String> hs = new HashSet<String>(); listAll(list, "", hs); } }3,没有重复元素的全排列
思路,不同之处在于只要所有元素的全排列,不要子集了。那么,在输出时加多一个判断就可以了,就是list的size要等于0.
package javainterview; import java.util.Arrays; import java.util.LinkedList; import java.util.List; public class Q7_1_1_c { public static void listAll(List<Integer> candidate, String prefix){ if(candidate.size()==0 && prefix.length()!=0){ System.out.println(prefix); } for(int i=0; i<candidate.size(); i++){ List<Integer> temp = new LinkedList<Integer>(candidate); int item = (int)temp.remove(i); listAll(temp, prefix+item); } } public static void main(String[] args) { Integer[] array = {1,2}; List<Integer> list = Arrays.asList(array); listAll(list, ""); } }
为方便起见,不管是字符串全排列还是数组全排列,全部转化为LinkedList来处理
package javainterview; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; public class Permutation { public static List<String> permutation(String s){ List<String> res = new ArrayList<String>(); if(s==null) return res; List<Character> list = new LinkedList<Character>(); for(int i=0; i<s.length(); i++) list.add(s.charAt(i)); permutation(res, list, ""); return res; } public static void permutation(List<String> res, List<Character> list, String prefix){ if(list.size()==0) res.add(prefix); for(int i=0; i<list.size(); i++){ List<Character> temp = new LinkedList<Character>(list); char item = (char)temp.remove(i); permutation(res, temp, prefix+item); } } public static void main(String[] args) { // TODO Auto-generated method stub String s = ""; List<String> res = permutation(s); for(String item : res) System.out.println(item + ";"); } }
4, 有重复元素的全排列
思路:也是用一个HashSet来存放结果。
package javainterview; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; public class Q7_1_1_d { public static void listAll(List<Integer> candidate, String prefix, HashSet<String> hs){ if(candidate.size()==0 && prefix.length()!=0 && !hs.contains(prefix)){ System.out.println(prefix); hs.add(prefix); } for(int i=0; i<candidate.size(); i++){ List<Integer> temp = new LinkedList<Integer>(candidate); int item = (int)temp.remove(i); listAll(temp, prefix+item, hs); } } public static void main(String[] args) { Integer[] array = {1,1,2}; List<Integer> list = Arrays.asList(array); HashSet<String> hs = new HashSet<String>(); listAll(list, "", hs); } }