题目:
难度:Middle
相关话题:回溯算法
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路:
稍微复杂一点的回溯,主要用到了处理重复的方法,先排序,排序是为了能高效的处理重复,而不必使用hash
检查是否重复。
排序后,例如[1,1,2,2,3]
,如果我第一位是1
(索引0),已经做好了排列,那么下一次第一位是1
(索引1)就不需要再次计算排列了, 因为已经重复了。
因此处理重复条件之一:i>0 && nums[i-1]===nums[i]
,但是还不够,如果我现在第一位是2
,那么第二位是1
(索引1)应该是合理的, 但却和这个条件冲突了。
因此完整条件应该是if(i>0 && nums[i-1]===nums[i] && !used[i-1])continue
,为什么上一位没使用就可以跳过呢?
在我们第一次计算重复的时候,上一位一定是使用了,而当我们第二次计算重复值时,上一位是未使用的,因此可以正确避免重复的排列。
/**
* @来源: Javascript中文网 - 前端进阶资源教程 https://www.javascriptc.com/
* @介绍:一个致力于帮助开发者用代码改变世界为使命的平台,每天都可以在这里找到技术世界的头条内容
* @param {number[]} nums
* @return {number[][]}
*/
var permuteUnique = function(nums) {
let result=[],temp=[],aux=[]
nums.sort()
backtrack(result,temp,nums,aux)
return result
function backtrack(result,temp,nums,aux){
if(aux.length===nums.length){
result.push(aux.slice())
}
for(let i=0;i<nums.length;i++){
if(temp[i] || (i>0 && nums[i]===nums[i-1] && !temp[i-1] ))continue
temp[i]=true
aux.push(nums[i])
backtrack(result,temp,nums,aux)
temp[i]=false
aux.pop()
}
}
};
扩展阅读: