In mathematics, permutation and combination are very important. In algorithm, we will introduce several methods to find all permutations and all subsets of elements.
I. full arrangement
Full Permutation, if implemented by recursion, is the problem of element exchange, while if implemented by iteration, it is the problem of adding the current character before or after the formed character. Here, we use iteration, common recursion and multiple recursion + backtracking respectively.
Iterative implementation
//Iterative implementation, subproblem: add before, add after, add in the middle static List<String> getPermutation(String s) { List<String> res = new ArrayList<>(); res.add(s.charAt(0)+""); for(int i=1;i<s.length();i++) { List<String> res_new = new ArrayList<>(); char c = s.charAt(i); for(String e:res) { String str = c + e; res_new.add(str);//Add to the front str = e + c; res_new.add(str);//Add to the back for(int j=1;j<e.length();j++) { str = e.substring(0,j)+c+e.substring(j); res_new.add(str); } res = res_new; } } System.out.println(res.size()); return res; }
Recursive implementation
/** * Recursive total permutation, subproblem * @param s * @param k Pointer to the character in the specified string child, generally 0 * @return */ static List<String> getPermutation1(String s,int k) { List<String> res_new = new ArrayList<>(); if(k == 0) { char ch = s.charAt(0); res_new.add(ch+""); return res_new; } List<String> res_old = getPermutation1(s,k-1); char c = s.charAt(k); for(String e : res_old) { String str = c + e; res_new.add(str); str = e + c; res_new.add(str); for(int i=1;i<e.length();i++) { str = e.substring(0,i)+c+e.substring(i); res_new.add(str); } } return res_new; }
Implementation of multiple recursion + backtracking
/** * Multiple recursion + backtracking * @param A Character array * @param k Current element subscript */ static void getPermutation2(char[] A, int k) { if(k==A.length-1) { for (char c : A) { System.out.print(c); } System.out.println(); return; } for(int i=k;i<A.length;i++) { swap(A,i,k);//Change every subsequent character to k getPermutation2(A,k+1); swap(A,i,k);//To flash back } } static void swap(char[] arr,int x,int y) { char tem = arr[x]; arr[x] = arr[y]; arr[y] = tem; }
2. Finding (non empty) subsets
Finding subsets is a problem for a collection to have or not to have this element. It can be implemented by iteration, recursion, or binary.
Note: there should be an empty set at the beginning. This empty set is the start state of the subset. If there is no empty set, that is, only one element set will be started. At this time, only one element will be added / not added, so there will be fewer other single elements.
Iterative implementation
/** * Iterative implementation * @param arr */ static Set<Set<Integer>> subset(int[] arr){ Set<Set<Integer>> res = new HashSet<>(); res.add(new HashSet<>());//Initializing a bitspace for(int i=0;i<arr.length;i++) { Set<Set<Integer>> newSet = new HashSet<>(); newSet.addAll(res); for(Set<Integer> set:res) { Set<Integer> clone = (Set<Integer>)((HashSet)set).clone(); clone.add(arr[i]); newSet.add(clone); } res = newSet; } return res; }
Recursive implementation
/** * Recursive implementation * @param arr * @param cur arr Array maximum subscript * @return */ static Set<Set<Integer>> subset(int[] arr,int cur) { Set<Set<Integer>> newSet = new HashSet<>(); if(cur == 0) {//Exit one must be placed in the front of the method Set<Integer> nullSet = new HashSet<>(); Set<Integer> fir_element = new HashSet<>(); fir_element.add(arr[0]); newSet.add(nullSet); newSet.add(fir_element); return newSet; } Set<Set<Integer>> oldSet = subset(arr,cur-1); for(Set<Integer> set : oldSet) { //Backup set Set<Integer> clone = (Set<Integer>)((HashSet)set).clone(); newSet.add(set);//Add collection without elements clone.add(arr[cur]);//Add elements to the backup set newSet.add(clone);//Add collection of elements } return newSet; }
Binary implementation
/** * Binary implementation * @param A * @return */ static Set<Set<Integer>> subset(int[] A){ char[][] bin_arr = new char[(int)Math.pow(2, A.length)][]; for(int i=0;i<bin_arr.length;i++) { bin_arr[i] = new StringBuilder(Integer.toString(i,2)).reverse().toString().toCharArray(); } Set<Set<Integer>> res = new HashSet<>(); for(int i=0;i<bin_arr.length;i++) { Set<Integer> tem = new HashSet<>(); for(int j=0;j<bin_arr[i].length;j++) { if(bin_arr[i][j] == '1')tem.add(A[j]); } res.add(tem); tem = null;//Reclaim the HashSet object pointed by tem; } return res; }