给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
给定的序列中包含有重复数字,因此结果不能有重复的元素存在。一种方法就是使用上一道题的代码,只是在最后保存结果时多加一个判断。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
if nums == []: return []
res = []
r = []
def backtrack(nums, pre, vis, index = 0):
print (pre)
if index == len(nums):
# 只有res中不包含和当前pre相同的元素时才保留
if pre not in res:
res.append(pre.copy())
return
for i in range(len((nums))):
if vis[i] == False:
vis[i] = True
pre.append(nums[i])
backtrack(nums, pre, vis, index + 1)
vis[i] = False
pre.pop()
nums = sorted(nums)
vis = [False] * len(nums)
backtrack(nums, [], vis, 0)
return res
但这样的方法多考虑了很多重复的情况,更好的方法是在递归的过程中进行剪枝。如果当前选择列表中的元素和上一次递归使用的元素相同,则使用它得到的结果必然是重复的,此时需跳过进行下一个元素的判断。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
res = []
l = len(nums)
# nums: 选择列表
# index:当前已有的元素个数
# pre:当前路径
# vis
def backtrack(nums, pre, index = 0):
# if nums == []表示当前选择列表为空,已到达叶子结点
if index == l:
res.append(pre.copy())
return
for i in range(len(nums)):
# 判断
if i > 0 and nums[i] == nums[i - 1]:
continue
pre.append(nums[i])
backtrack(nums[:i] + nums[i + 1:], pre, index + 1)
pre.pop()
if nums == []: return []
# 递归函数
nums = sorted(nums)
backtrack(nums, [], 0)
return res