摘要:排列组合,考察递归和回溯思想的运用
全排列
import java.util.*; public class HelloWorld { /** * 递归求全排列 */ static int[] arr = new int[]{1,2,3}; static List<List<Integer>> res = new ArrayList<>(); public static void main (String[] args) { permute(arr); System.out.println(res); } static List<List<Integer>> permute(int[] arr ){ if(arr.length == 0){ return res; } List<Integer> temp = new ArrayList<>(); generatePurmutation2(arr,0,temp); return res; } static void swap(int i,int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //交换回溯法 // begin 逐个考察,而 j 是工作指针进行交换 static void generatePurmutation(int[] arr,int begin,List<Integer> temp){ // 当begin指向最后一个元素时,此时已经可以结束了 if(begin == arr.length-1){ for (int i =0;i<arr.length ;i++ ){ temp.add(arr[i]); } res.add(new ArrayList<Integer>(temp)); temp.clear(); return ; } for (int j=begin;j<=arr.length-1;j++){ swap(begin,j); generatePurmutation(arr,begin+1,temp); swap(begin,j); //回溯需要交换到原始状态 } return ; } // 全考察剪支法 // 借用一个used数组存储已选的元素 static boolean[] used = new boolean[arr.length]; static void generatePurmutation2(int[] arr,int begin,List<Integer> temp){ if(begin == arr.length){ res.add(new ArrayList<Integer>(temp)); return ; } //全考察 for (int i = 0 ;i< arr.length ;i++ ){ if(!used[i]){ //此处判断就是为了剪支 temp.add(arr[i]); used[i] =true; generatePurmutation2(arr,begin+1,temp); //回溯 used[i] =false; temp.remove(temp.size()-1); } } } }
求组合
import java.util.*; public class HelloWorld { public static void main(String[] args) { res = combine(4,2); System.out.println(res); } static List<List<Integer>> res = new ArrayList<>(); static List<List<Integer>> combine(int n,int k){ if(n<0|| k<0|| k>n){ return res; } List<Integer> c = new ArrayList<>(); generateCombination(n,k,1,c); return res; }
求子集回溯法
static void generateCombination(int n,int k,int start,List<Integer> temp){ if(temp.size() == k ){ res.add(new ArrayList<Integer>(temp)); return ; } if(start>4){ //求子集法,需要加限制条件,不然会爆 return ; } // for (int i=start;i<= n ;i++ ){ int i = start; temp.add(i); generateCombination(n,k,i+1,temp); temp.remove(temp.size()-1); generateCombination(n,k,i+1,temp); // } }
循环回溯法
static void generateCombination(int n,int k,int start,List<Integer> temp){ if(temp.size() == k ){ res.add(new ArrayList<Integer>(temp)); return ; } for (int i=start;i<= n ;i++ ){ temp.add(i); generateCombination(n,k,i+1,temp); temp.remove(temp.size()-1); // generateCombination(n,k,i+1,temp); } }