最近做了 LeetCode 上关于全排列的题目,下面将解决排列问题的最普通经典的解法分享如下,希望网友们批评指正:

问题描述

给定一些数字,这些数字中包含重复的数字,求这些数字组成的不重复的全排列。

例如给定数输入:
[1,1,2]
返回:
 
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]


解题思路

传统排列问题

解决全排列问题的常用思路是递归,我们先来看一个简单的例子:

给定集合为 [1,2,3]

那么则建立两个集合,一个是已经被安放了数字的集合(solved),另一个尚未是未被安放数字的集合(unsolved)。那么思路就是:

  1. 设定初始 solved = [],unsolved = [1,2,3]
  2. 将 unsolved 集合中剩下的每个数字逐个试着放入 solved 集合中,放入之后将每次的结果进行保存
  3. 重复步骤 2 ,当 unsolved 集合为空时,solved 集合就是一个排列的解,并将其放入解集中
  4. 重复步骤 2 、3 直到找遍每一种可能

解空间如下图(下划红线为一个答案):

python全排列递归 输入只有一个数字 全排列 递归 python_全排列

源代码如下(即 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

以上就是文章的全部内容,希望可以帮到大家,文章内容如有不足或者错误,恳请大家批评指正。