关于全排列

对于全排列问题,我们一般使用dfs思想去解决问题,也就是需要使用递归,常见的方法有两种,数组标记法和交换法,交换法会相对更加难以理解一点,所以我一般倾向于使用数组标记法.
下面给出常见的模板(java实现):

  1. 数组标记法
import java.util.Scanner;

public class 全排列_标记法 {
	static Scanner sc = new Scanner(System.in);
	static int n = sc.nextInt();
	static int result[] = new int[n+1];
	static int vis[]  = new int[n+1];
	public static void main(String[] args) {
		DFS(1);
	}
	private static void DFS(int step) {
		if(step >= n+1) {
			print();
			return;
		}
##关键就是这里的理解 核心思想就是用标记数组来保证dfs的走位,也可以自行在颅内编译一下,值得注意的是for循环在当前函数正在执行的次数,搞清楚此即可. 值得注意的是,标记的数组标记的是目前已经使用了哪些数字(或者说具体的全排列元素)## 
//for循环遍历目前哪个元素还未被使用进行填充
//for循环相当于搜索 赋值为0操作相当于回溯
		for(int j = 1 ; j <= n ; j++) {
			if(vis[j] == 0) {
				vis[j] = 1;//标记数组
				result[step] = j;
				DFS(step+1);
				vis[j] = 0;//回溯
			}
		}
	}
	private static void print() {
		for(int i = 1; i <= n; i++) {//对应问题3
			System.out.printf("%5d",result[i]);
		}
		System.out.println();
	}	
}
  1. 交换法
import java.util.Scanner;

public class 生成排列交换法 {
	static Scanner sc = new Scanner(System.in);
	static int ans = 0;
	static int n = sc.nextInt();
	static int pre[] = new int[n];
    
	public static void main(String[] args) {
		for(int i = 0 ; i < pre.length ; i++) {
			pre[i] = sc.nextInt();
		}
		dfs(0);//从第0层,指最上层为0
                /*

                *此处的dfs的参数为0,是指将最上层当作第0层,也可以改为1,但对应dfs函数中的 

                *if(step == n)就要相应的改动                                       

                */
		System.out.println(ans);
	}
	public static void dfs(int step) {
		if(step == n) {
			ans++;
			print();
		}
		for(int i = step ; i < n; i++) {
                        //此循环体一定要重点理解,弄清原理主要就靠这循环体
//交换
			swap(i,step);//对应图中的元素交换

			dfs(step+1);
//恢复原来的状态
			swap(step,i);

		}	
	}
	public static void print() {
		for(int i = 0 ; i < n ; i++) {
			System.out.printf("%5d",pre[i]);
		}
		System.out.println();
	}
	public static void swap(int i, int j) {
		int temp;
		temp = pre[i];
		pre[i] = pre[j];
		pre[j] = temp;
	}

对于dfs的算法,大家都可以通过画图的形式来加深自己的理解.

下面举个栗子:如何实现1-N-1的全排列

import java.util.Scanner;
public class Main {
    static Scanner sc = new Scanner(System.in);
    static int n = sc.nextInt();
    static int arr[] = new int[n + 1];
    static int brr[] = new int[n + 1];

    public static void main(String[] args) {
        DFS(0);
    }

    private static void DFS(int step) {
        if (step == n) {
            for (int i = 0; i <n; i++) {
                System.out.print(arr[i]+" ");
            }
            System.out.println();
        }
        for (int j = 1; j <= n; j++) {
            if (brr[j] == 0) {
                brr[j] = 1;
                arr[step] = j;
                DFS(step + 1);
                brr[j] = 0;
            }
        }
    }
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值