JAVA回溯实现全排列和组合
JAVA不像C++有next_permutation函数可以方便实现全排列,因此需要自己实现。
函数perm用于实现数组中由下标p到下标q之间元素的全排列。为了便于理解我们举例 nums为 1 2 3 4,对于这四个数字我们可以分为四类
第一类为以1作为头部后面剩余的数字进行全排列,第二类以2作为头部后面剩余的数字进行全排列。如此类推。根据这种原理我们就可以写出一个递归过程。
1 public class Permutations { 2 public static List<List<Integer>> permute(int[] nums) { 3 List<List<Integer>> res = new ArrayList<>(); 4 if(null==nums||nums.length==0){ 5 return res; 6 } 7 List<Integer> l0 = new ArrayList<>(); 8 l0.add(nums[0]); 9 res.add(l0); 10 for(int i=1;i<nums.length;++i){ 11 List<List<Integer>> new_ans = new ArrayList<List<Integer>>(); 12 for(int j=0;j<=i;++j){ 13 for(List<Integer> l:res){ 14 List<Integer> new_l = new ArrayList<Integer>(l); 15 new_l.add(j, nums[i]); 16 new_ans.add(new_l); 17 } 18 } 19 res = new_ans; 20 } 21 return res; 22 } 23 24 public static void main(String[] args) { 25 int[] nums = {1,2,3}; 26 System.out.println(permute(nums)); 27 } 28 }
理解了上述的思路稍作修改我们就可以写出从1....n中的k个数字的组合,代码如下
1 public class Combinations { 2 public static List<List<Integer>> combine(int n, int k) { 3 List<List<Integer>> res = new ArrayList<>(); 4 combine(res, new ArrayList<Integer>(), 1, n, k); 5 return res; 6 } 7 8 public static void combine(List<List<Integer>> res,List<Integer> comb,int start,int n,int k){ 9 if(k==0){ 10 res.add(new ArrayList<Integer>(comb)); 11 return; 12 } 13 14 for(int i=start;i<=n;i++){ 15 comb.add(i); 16 combine(res, comb, i+1, n, k-1); 17 comb.remove(comb.size()-1); 18 } 19 } 20 21 public static void main(String[] args) { 22 List<List<Integer>> res = combine(5, 2); 23 System.out.println(res); 24 } 25 }