题目描述
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例
示例1:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
题目分析
题目要求很简单,就是给定一个数组,然后返回数组中所有能够排列出的且不重复的数组。
解题思路
那么这题就不同于之前的题目了,这题得用回溯算法。
那么什么是回溯算法呢?回溯算法其实就是穷举法,不过回溯算法中用了剪枝函数,剪去了一些不可能达到最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。
这么说的话,可能还不是那么的具体,那就看这张图吧。
就本题而言,因为需要返回不重复的数组,那么回溯中就要一些剪枝的操作,只有碰到跟自己不同的才会继续向下执行,碰到相同的就跳过;每一个分支递归结束后,都需要去另一个分支进行递归,所以,我们需要撤销当前的选择,回到之前的选择状态,进入下一个分支重复之前的操作。
就有点类似于树的深度优先遍历,就一条道走到底,发现走不通了就回到上一级分支,如果上一级分支还有未走过的,就从未走过的分支开始;就这样循环往复,直到每一条分支都走完。
AC代码
var permute = function(nums) {
let res = []
let recursion = (path, set) => {
if(path.length == nums.length) { // 当 path 中长度跟给定数组的长度相同时
// 说明已经有一条path满足条件了,结束当前递归
res.push(path.concat()) // 将满足条件的 path 放进集合数组中
return // 递归出口
}
for(let i = 0 ; i < nums.length; i++) { // 遍历
if(!set.has(nums[i])) { // 如果set中不存在该元素
path.push(nums[i]) // 就将它push进path中
set.add(nums[i]) // 同时将该元素存进 set 中
recursion(path,set) // 每一次递归结束之后,都需要将当前的选择清除
path.pop() // 所以path就需要一步步的将当前选择删除
set.delete(nums[i]) // set跟path一样
}
}
}
recursion([],new Set()) // 递归入口
return res
};
总结
对于回溯算法还是需要多多练习呀,我相信多做些用回溯的算法题会对回溯了解更深一些。如果文中有什么讲的不好的或者需要修改的地方,欢迎到评论区留言,好让我及时发现问题,谢谢各位xdm了。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情