关于错排的定义,可以自行百度
其中也有错排种数的计算
这个算法是基于全排列,在全排列添加条件。采用回溯,过程有点类似于剪支(那个条件的判断是否就不用继续执行了)
import java.util.*;
public class Derangements {
public List<List<Integer>> derangements(int[] nums) {
int len = nums.length;
// 使用一个动态数组保存所有可能的全排列
List<List<Integer>> res = new ArrayList<>();
if (len == 0) {
return res;
}
// 错排的定义是:n个有序的元素应有n!种不同的排列。如若一个排列式的所有的元素都不在原来的位置上,则称这个排列为错排
boolean[] used = new boolean[len];
Deque<Integer> path = new ArrayDeque<>(len);
dfs(nums, len, 0, path, used, res);
return res;
}
private void dfs(int[] nums, int len, int depth,
Deque<Integer> path, boolean[] used,
List<List<Integer>> res) {
if (depth == len) {
// res.add(new ArrayList<>(path));
// System.out.println(Arrays.toString(path.toArray(path.toArray(new Integer[0]))));
System.out.println(Arrays.toString(path.toArray()));
return;
}
for (int i = 0; i < len; i++) {
// 没有被使用,并且当前要使用的元素与当前位置不对应
if (!used[i] && i!=depth) {
path.addLast(nums[i]);
used[i] = true;
// System.out.println(" 递归之前 => " + path);
dfs(nums, len, depth + 1, path, used, res);
used[i] = false;
path.removeLast();
// System.out.println("递归之后 => " + path);
}
}
}
}