「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」
Hope is a good thing, maybe the best of things. And no good thing ever dies.
前言
回溯算法是对树形或者图形结构执行一次深度优先遍历,实际上类似枚举的搜索尝试过程,在遍历的过程中寻找问题的解。
深度优先遍历有个特点:当发现已不满足求解条件时,就返回,尝试别的路径。此时对象类型变量就需要重置成为和之前一样,称为「状态重置」
题目
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列
你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1]
输出:[[1]]
题目分析
递归参数
-
递归函数参数
首先排列是有序的,也就是说[1,2] 和[2,1] 是两个集合
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次 1,所以处理排列问题就不用使用
startIndex了。但排列问题需要一个
used数组,标记已经选择的元素 -
递归终止条件
当收集元素的数组
path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。 -
单层搜索的逻辑
因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。
而
used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次
解题
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
const res = [], path = [];
backtracking(nums, nums.length, []);
return res;
function backtracking(n, k, used) {
if(path.length === k) {
res.push(Array.from(path));
return;
}
for (let i = 0; i < k; i++ ) {
if(used[i]) continue;
path.push(n[i]);
used[i] = true; // 同支
backtracking(n, k, used);
path.pop();
used[i] = false;
}
}
};
附:
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」