1. 指数型枚举
n个数,最少可以选择0个,最多可以选择n个,定义一个选择数组vis, vis[i]为true表示选择数字i, 一共有 2 n 2^n 2n种情况,当递归的层数达到n时,输出选择的结果
import java.util.Scanner;
public class Main {
public static void main(String[] args){
int n;
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
n=sc.nextInt();
boolean[] vis=new boolean[n+1];
dfs(n,vis,1);
}
}
public static void dfs(int n,boolean[] vis,int index){
if(index>n){
//index==n+1 index==n时还需要添加
for(int i=1;i<=n;i++){
if(vis[i]){
System.out.print(i+" ");
}
}
System.out.println();
return;
}
vis[index]=true;
dfs(n, vis, index+1);//选择第i个数 继续往下递归
vis[index]=false;
dfs(n, vis, index+1);//不选择第i个数 继续往下递归
}
}
2. 组合型枚举
组合型枚举呈现一种"只看后面的"的趋势,即如果选择了当前数字i, 后面可能选择的是i+1之后的,因为1 2 3
和3 2 1
是相同的,因此只需要按字典序递增去考虑,具体做法: 设置一个集合,存储被选中的数,第一层递归时有n种选择,第2层递归时有n-1种选择,第3层递归时有n-3种选择…在当前层递归时,对于某个数可以选择也可以不选择
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static ArrayList<Integer> list = new ArrayList<>();
public static void main(String[] args) {
int n, m;
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
n = sc.nextInt();
m = sc.nextInt();
dfs(n, m, 1);
}
}
public static void dfs(int n, int m, int index) {
if(list.size()+(n-index+1)<m){
//1个优化 当剩余的数不足够形成m个时 直接退出本层递归
return;
}
if (list.size() == m) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
System.out.println();
return;
}
for(int i=index;i<=n;i++){
list.add(i);//在当前层递归选择数字i
dfs(n,m,i+1);//下一次从i+1开始选 不会发生重复
list.remove(list.size()-1);//不选择数字i 可能会选择当前层递归后面的i+1 i+2....n也可能不选
}
}
}
3. 排列型枚举
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static ArrayList<Integer> list = new ArrayList<>();
static boolean[] vis;
public static void main(String[] args) {
int n;
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
n = sc.nextInt();
vis = new boolean[n + 1];
dfs(n);
}
}
public static void dfs(int n) {
if (list.size() == n) {
//选中了n个数
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
System.out.println();
return;
}
for (int i = 1; i <= n; i++) {
//不同于组合 这里的循环每层递归时都是1~n
if(!vis[i]){
//避免出现1 1 1 这种重复的情况
vis[i]=true;
list.add(i);
dfs(n);
list.remove(list.size()-1);
vis[i]=false;
}
}
}
}