题目
题目来源:力扣(LeetCode)
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
思路分析
回溯
- 先对数组进行升序排序,以保证相同的数字相邻
- 然后从左到右遍历数组,如果当前数字和前一个相同,即nums[i] == nums[i - 1],当前数字已经被选过,则直接跳过当前数字
/*** @param {number[]} nums* @return {number[][]}*/var permuteUnique = function (nums) {let res = [];let len = nums.length// 对数组进行升序排序,保证相同的数字都相邻nums.sort((a, b) => a - b)unique([], 0)return resfunction unique(arr) {// 个数选够了,将当前排列加入结果中if (arr.length == len) {res.push([...arr])return}// 枚举出所有的选择for (let i = 0; i < nums.length; i++) {// 跳过,避免产生重复的排列if (nums[i] == nums[i - 1]) continue// 将当前的数字加入排列中arr.push(nums[i])// 由于当前数字已经加入排列中,因此将当前数字从nums数组中删除// 直接将当前已选择的数字从原数组中删除或重新加入,减少了额外定义变量来记录当前数字是否已被选择nums.splice(i, 1)// 基于已选的数字,递归继续选择未选的数字unique(arr)// 从 排列中撤销当前选择的数字,并将当前数字重新放回nums数组中,这一步是回溯nums.splice(i, 0, arr.pop())}}};
