47.permutations-ii.md 2.6 KB
Newer Older
L
luzhipeng 已提交
1
## 题目地址
L
luzhipeng 已提交
2
https://leetcode.com/problems/permutations-ii/description/
L
luzhipeng 已提交
3 4 5

## 题目描述
```
L
luzhipeng 已提交
6
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
L
luzhipeng 已提交
7

L
luzhipeng 已提交
8
Example:
L
luzhipeng 已提交
9

L
luzhipeng 已提交
10 11
Input: [1,1,2]
Output:
L
luzhipeng 已提交
12
[
L
luzhipeng 已提交
13 14 15
  [1,1,2],
  [1,2,1],
  [2,1,1]
L
luzhipeng 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
]

```

## 思路

这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。

这种题目其实有一个通用的解法,就是回溯法。
网上也有大神给出了这种回溯法解题的
[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。
除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。

我们先来看下通用解法的解题思路,我画了一张图:

![backtrack](../assets/problems/backtrack.png)

通用写法的具体代码见下方代码区。

## 关键点解析

- 回溯法
- backtrack 解题公式


## 代码

```js
/*
 * @lc app=leetcode id=47 lang=javascript
 *
 * [47] Permutations II
 *
 * https://leetcode.com/problems/permutations-ii/description/
 *
 * algorithms
 * Medium (39.29%)
 * Total Accepted:    234.1K
 * Total Submissions: 586.2K
 * Testcase Example:  '[1,1,2]'
 *
 * Given a collection of numbers that might contain duplicates, return all
 * possible unique permutations.
 *
 * Example:
 *
 *
 * Input: [1,1,2]
 * Output:
 * [
 * ⁠ [1,1,2],
 * ⁠ [1,2,1],
 * ⁠ [2,1,1]
 * ]
 *
 *
 */
function backtrack(list, nums, tempList, visited) {
  if (tempList.length === nums.length) return list.push([...tempList]);
  for (let i = 0; i < nums.length; i++) {
    // 和46.permutations的区别是这道题的nums是可以重复的
    // 我们需要过滤这种情况
    if (visited[i]) continue; // 不能用tempList.includes(nums[i])了,因为有重复
    // visited[i - 1] 这个判断容易忽略
    if (i > 0 && nums[i] === nums[i - 1] && visited[i - 1]) continue;

    visited[i] = true;
    tempList.push(nums[i]);
    backtrack(list, nums, tempList, visited);
    visited[i] = false;
    tempList.pop();
  }
}
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permuteUnique = function(nums) {
  const list = [];
  backtrack(list, nums.sort((a, b) => a - b), [], []);
  return list;
};
```

## 相关题目

- [39.combination-sum](./39.combination-sum.md)
- [40.combination-sum-ii](./40.combination-sum-ii.md)
- [46.permutations](./46.permutations.md)
- [78.subsets](./78.subsets.md)
- [90.subsets-ii](./90.subsets-ii.md)