LeetCode 47. Permutations II
2020-06-05 12:19:19
# leetcode
# core problems
Problem
1. 题目简述
给出一列有重复的数,找出其所有的全排列。例如:
Input: [1,1,2]
Output:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
2. 算法思路
back tracking回溯法的经典题目之一,LeetCode 46. Permutations的进阶版,问题在于我们怎么去应对这个重复数字的问题。
如果按照以往的思路,对于这种有重复数字的,我们首先需要对数组进行排序,然后才能更好地去对重复数字进行处理。
那么我们能否还像permutation
1的时候,交换然后再找全排列么?不行的,这种去重方式的核心思想在于后面不会再出现比当前更小的数字,这么说可能有点抽象,我们来看个例子。
我们给出一个排好序的数组[1, 1, 2, 2, 3],按照如上思路的话:
1. 从第1个数开始,分别和1、2、3、4、5进行替换,然后寻找其后面的全排列;
2. 为了不重复,我们每次(除了首次的自我替换)寻找替换的数字的时候,都要找到和当前不一样的数字为止,例如第1个1,和第2个1就不会进行替换,以此类推;
3. 那么问题会出在哪里呢?当我们需要替换第1个1和末尾的3时,数组变为[3, 1, 2, 2, 1],然后我们找出[1, 2, 2, 1]的全排列;
4. 按照我们的逻辑,1先和第1个2替换,然后跳过第2个2,然后判断到了第2个1,第2个1和它之前的数字2是不同的,因此我们再次替换,到这里我们就会发现出现了重复,明明1和1不应该再替换的,在这里却被再次替换,所以会多出很多重复。
因此我们去重的方式其实可以更简单一点,用hashset来判断是之前是否和同样的元素交换过就可以了,而且原始数组不需要排序也可以。
回溯法
注意这里去重的方式和subset 2以及combination sum
2的去重方式完全不同,具体原因在上面已经详细描述了,建议自己尝试写一下,这里把错误的代码放在文章末尾,大家有兴趣可以自己debug一下,看看哪里出了问题。
这里我们使用hashset来去重。
1 | class Solution { |
错误版本的代码,警戒
1 | class Solution { |