一、题目描述
二、解题思路
对于这种使用回溯法的题目,我们都可以先画一个解集树看看:
根据题目条件,可以得知其约束条件如下:
不能产生重复的排列,从上面的图可以看出,要避免重复排列要做到两点:
- 树的同一路径上不选择索引相同的数字,因为这个数字已经被用过了。比如:在一个排列中,如果第一次选择了第一个1,那么第二次就不能再选择第一个1,只能选择第二个1。
- 树的同一层不能选择相同的数字,即使它们的索引是不同的。比如:对于
[1,1,2]
,如果第一个排列以第一个1开头,那么如果第二个排列以第二个1开头,那么往后的排列都是相同的,因此可以在第二个排列中选择以1开头
针对第一点,需要用一个额外的数组used[i]
来保证,针对第二点,则可以利用下面代码来保证:
if (nums[i-1]==nums[i] && i-1>=0 && !used[i-1]) continue
然后就是回溯了,最后当数组达到nums的长度时就可以退出当前递归。
三、代码实现
var permuteUnique = function(nums) {
const res = []
const len = nums.length
const used = new Array(len)
nums.sort((a,b)=>a-b)
const dfs = (list) =>{
if(list.length == len){
res.push(list.concat()) //这里要将数组拷贝一份再push才能得出结果,不然就会加入空数组,不知道为什么...
return
}
for(let i=0;i<len;i++){
if (nums[i-1]==nums[i] && i-1>=0 && !used[i-1]) continue //注意这里的!used[i-1]是为了避免把第一个2弹出来后,轮到第二个2时,再次把它=第二个2加入进去
if (used[i]) continue
list.push(nums[i])
used[i] = true
dfs(list)
list.pop()
used[i] = false
}
}
dfs([])
return res
};