排列与组合
摘要:排列组合,考察递归和回溯思想的运用
全排列
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);
}
}