最近做了 LeetCode 上关于全排列的题目,下面将解决排列问题的最普通经典的解法分享如下,希望网友们批评指正:
问题描述
给定一些数字,这些数字中包含重复的数字,求这些数字组成的不重复的全排列。
例如给定数输入:
[1,1,2]
返回:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
解题思路
传统排列问题
解决全排列问题的常用思路是递归,我们先来看一个简单的例子:
给定集合为 [1,2,3]
那么则建立两个集合,一个是已经被安放了数字的集合(solved),另一个尚未是未被安放数字的集合(unsolved)。那么思路就是:
- 设定初始 solved = [],unsolved = [1,2,3]
- 将 unsolved 集合中剩下的每个数字逐个试着放入 solved 集合中,放入之后将每次的结果进行保存
- 重复步骤 2 ,当 unsolved 集合为空时,solved 集合就是一个排列的解,并将其放入解集中
- 重复步骤 2 、3 直到找遍每一种可能
解空间如下图(下划红线为一个答案):
源代码如下(即 LeetCode 上的前一题):
class Solution:
ans = []
def ques46_recursive(self,solved,unsolved):
if unsolved == []:
temp = []
for x in solved:
temp.append(x)
self.ans.append(temp)
else:
for i in range(len(unsolved)):
solved.append(unsolved[i])
temp = unsolved.pop(i)
self.ques46_recursive(solved,unsolved)
solved.pop()
unsolved.insert(i,temp)
def permute(self, nums: List[int]) -> List[List[int]]:
self.ans = []
self.ques46_recursive([],nums)
return self.ans
本题场景
然而,在本题的场景中,当给定的数字中出现重复的数字时,会出现重复的答案。
一个最容易想到的改进方法就是:当得到一个排列的解时,搜寻解集中是否存在该解,如存在就不进行操作,如果不存在则加进解集中,然而这种方法费时费空间。
因为答案重复的原因是在上面的步骤 2 中,从 unsolved 集合向 solved 集合中逐个放入数字时会放入重复的元素,所以我尝试使用 Python 中的字典(哈希表)来保存 unsolved 集合。键名表示数字,键值表示该数字的个数。代码如下:
class Solution:
def permuteUnique_recursive(self,local_ans,numsdict,global_ans):
finish = 0
for x in numsdict:
if numsdict[x] > 0:
finish = 1
numsdict[x] -= 1
local_ans.append(x)
self.permuteUnique_recursive(local_ans,numsdict,global_ans)
local_ans.pop()
numsdict[x] += 1
if finish == 0:
temp = []
for x in local_ans:
temp.append(x)
global_ans.append(temp)
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
global_ans = []
numsdict = {}
for x in nums:
if x in numsdict:
numsdict[x] += 1
else:
numsdict[x] = 1
self.permuteUnique_recursive([],numsdict,global_ans)
return global_ans
以上就是文章的全部内容,希望可以帮到大家,文章内容如有不足或者错误,恳请大家批评指正。