目录
题目链接
题目描述
给定一系列数字组成的列表nums,列表中可能会含有重复数字,返回列表元素的所有不重复排列结果。
示例
输入:nums = [1,1,2]
输出:[[1,1,2] , [1,2,1] , [2,1,1]]
输入:nums=[1,2,3]
输出:[ [1,2,3] , [1,3,2] , [2,1,3] , [2,3,1] , [3,1,2] , [3,2,1]]
解决思路一
这个问题是46 Permutations问题的扩展,列表nums中可能含有重复元素。
将这个问题看作树的深度优先搜索更好理解。如对于示例中的[1,1,2],对应要遍历的树为
在完成第二层第一个子节点[1]的深度优先搜索后,能够得到[1,1,2],[1,2,1]两种组合,第二层第二个子节点也为1,如果把这个子节点当作父节点往下进行深度优先遍历的话,会得到重复的元素组合。因此在用for循环体遍历同层节点前要对该层节点进行排序,使相同的元素能够左右相邻,同时对于这种情况(i!=0 and nums[i] == nums[i-1])要利用continue关键字跳过。
Python实现
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
def duplicate_dfs(nums,path,return_list):
if not nums:
return_list.append(path) #深度优先搜索到了最后一层,将得到的路径添加到最后返回的return_list中。
else:
#对子节点列表进行排序,这样相等的数字会左右相邻
nums.sort()
for i in range(len(nums)): #同层元素遍历
if(i != 0 and nums[i] == nums[i-1]):#如果同层元素中后一个元素和前一个元素相等,就要把这个元素跳过去。
continue
duplicate_dfs(nums[:i]+nums[i+1:],path+[nums[i]],return_list) #深度优先搜索
return_list = []
duplicate_dfs(nums,[],return_list)
return return_list
解题思路二
可以用回溯思想来考虑这个问题。回溯思想相当于带有“剪枝”的穷举法,一般用来寻找带有约束条件问题的全部或部分解。回溯思想是指在当前情况下面临着多种选择,对每种选择进行尝试,如果发现某个选择违反了设定的返回条件就返回,如果尝试某种选择直到最后,确定该选择是正确解,那么就将这个解加入到解集中。用回溯法解决问题时,要考虑三个要素:选择,限制和结束条件。
对于这个问题来说,从输入数组中逐个选择元素组成最后的排列,长度为N的排列,需要N次选择才能得到。每次将一个元素从剩下可用的数组元素中选出来加入排列,再在当前选择的基础上逐个从剩余元素中选择元素,当最后得到的排列个数为N时,把这个排列加入到解集中。回溯模板及更详尽分析见【leetcode-Python】- 回溯-46 Permutations。
代码一样,但是对于参数的理解有些差异。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
result = []
track = []
nums.sort() #仅进行一次排序
def backtrack(track,options):
if not options: #可选节点为空时说明到达结束条件,返回
result.append(track)
return
for i in range(len(options)):
if i != 0 and options[i] == options[i-1]: #越过重复的选择
continue
backtrack(track+[options[i]],options[0:i]+options[i+1:])
backtrack(track,nums)
return result