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