全排列
作者:互联网
求出N个数字的全排列
采用深度优先搜索
将每个数字看成树的节点
然后借助一个长度为N的数组,标识某个数字是否“被使用过”
当遍历到树的叶节点也就是深度为N时,将这一节点往上到根节点的路径保存到结果集中
大致遍历过程,举例 [1, 2, 3 ,4]
第一层可选1, 2, 3, 4
,先选出1
,往下一层
第二层可选2, 3, 4
,先选出2
按这样到第四层时路径就是1-2-3-4
为一种结果添加到结果
然后回溯到第三层,这一次第三层选出4
,于是到第四层是路径为1-2-4-3
显然第三层的两种可能都选过了,再回溯到第二层
第二层这次选择2
后面的3
,然后按前面的规律到最后路径为1-3-2-4
然后老规矩返回到第三层选择4
,最后第四层时路径为1-3-4-2
此时回溯到第三层时两种可能都选过了,再回溯到第二层选出4
,重复上述过程
当第二层三种可能都选过时,返回到第一层选出2
,以2
为根节点重复上述过程
public static List<List<Integer>> permutations(int n) {
boolean[] used = new boolean[n];
Deque<Integer> path = new LinkedList<>();
List<List<Integer>> result = new LinkedList<>();
dfs(n, path, result, used);
return result;
}
/**
* 深度优先搜索
*
* @param n N个数
* @param path 深度优先搜索的路径(中间结果)
* @param result 结果集
* @param used 记录各个数是否已经"取出"
* @return void
*/
private static void dfs(int n, Deque<Integer> path, List<List<Integer>> result, boolean[] used) {
// 如果路径中的节点已经有n个, 则添加到结果集
if (path.size() == n) {
result.add(new LinkedList<>(path));
} else {
// 遍历N个数
for (int i = 0; i < n; i++) {
// 如果当前数未被"取出"
if (!used[i]) {
// 标记为已"取出"
used[i] = true;
// 当前数添加到路径
path.addLast(i + 1);
dfs(n, path, result, used);
// 递归返回时将当前数重新标记为未"取出"
used[i] = false;
// 从路径中移出当前节点
path.removeLast();
}
}
}
}
标签:排列,第三层,路径,used,result,path,节点 来源: https://blog.csdn.net/qq_43269370/article/details/112155893