三道枚举类型题(指数型、组合型、排列型)

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 33 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;
            }
        }
    }

}

猜你喜欢

转载自blog.csdn.net/qq_43478694/article/details/126652607