【LeetCode每日一练】47. 全排列 II(中等|JS|回溯算法)

一、题目描述

在这里插入图片描述

二、解题思路

对于这种使用回溯法的题目,我们都可以先画一个解集树看看:
在这里插入图片描述
根据题目条件,可以得知其约束条件如下:

不能产生重复的排列,从上面的图可以看出,要避免重复排列要做到两点:

  1. 树的同一路径上不选择索引相同的数字,因为这个数字已经被用过了。比如:在一个排列中,如果第一次选择了第一个1,那么第二次就不能再选择第一个1,只能选择第二个1。
  2. 树的同一层不能选择相同的数字,即使它们的索引是不同的。比如:对于[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
};

猜你喜欢

转载自blog.csdn.net/weixin_40764047/article/details/110794078