问题描述:
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2] 输出:[[1,1,2], [1,2,1], [2,1,1]]
问题分析:
还是回溯法,只是这次,在进行深度优先搜索的之前,先进行一次排序,目的就是为了把相同的数字放到一起,在每层选择中,如果同数字出现重复,那么就选择一次,并依次类推。走到头,添加到输出数组,并回溯到上一层,直到结束。
Python3递归实现:
# @Time :2018/7/12
# @Author :LiuYinxing
# 递归实现 bfs
# 第二种方法稍微快一点
class Solution:
def permuteUnique(self, nums): # 递归方法1
nums.sort() # 先排序
res = [] # 保留结果
def dfs(nums, path, res):
if len(nums) == 0: # 选到头,添加到res中,这里是递归出口,可以加return也可以不加,后续一定会结束。
res.append(path)
for i in range(len(nums)):
if i > 0 and nums[i] == nums[i - 1]: continue # 每一层选择中如果重复,则只进行一次深度搜索
dfs(nums[0:i] + nums[i+1:], path + [nums[i]], res)
dfs(nums, [], res)
return res
def permuteUnique1(self, nums): # 递归方法2
nums.sort() # 先排序
res = [] # 保留结果
def dfs(nums=nums, path=[]):
if len(nums) == 0: # 选到头,添加到res中,这里是递归出口,可以加return也可以不加,后续一定会结束。
res.append(path)
for i in range(len(nums)):
if i > 0 and nums[i] == nums[i - 1]: continue # 每一层选择中如果重复,则只进行一次深度搜索
dfs(nums[0:i] + nums[i+1:], path + [nums[i]])
dfs()
return res
def permuteUnique2(self, nums):
res = [[]]
for n in nums:
tmpres = []
for l in res:
for i in range(len(l) + 1):
tmpres.append(l[:i] + [n] + l[i:])
if i < len(l) and l[i] == n: break # handles duplication
res = tmpres
return res
if __name__ == '__main__':
solu = Solution()
print(solu.permuteUnique(nums=[1, 1, 2]))
Python3非递归实现:
我们每次选择一个元素,生成一个临时的res结果集, 然后继续选择元素,并把这个元素,插入上次生成的临时res集中,在插入的过程中,每一个缝隙插入一次,并作为一个新的子集添加到res中,直到结束。在处理重复数字的时候,如果发现插入的数字,与当前缝隙边的上的元素一样,就这个子集就停止插入,进行下一个子集的处理。
# @Time :2018/7/12
# @Author :LiuYinxing
# 插空法
# 经过测试,这种方法并没有递归快
class Solution:
def permuteUnique(self, nums):
res = [[]]
for n in nums:
tmpres = []
for l in res:
for i in range(len(l) + 1):
tmpres.append(l[:i] + [n] + l[i:])
if i < len(l) and l[i] == n: break # 停止插入,处理下一个子集
res = tmpres
return res
if __name__ == '__main__':
solu = Solution()
print(solu.permuteUnique(nums=[1, 1, 2]))
欢迎指正哦。