Leetcode 47. Permutations II

该博客探讨了如何在生成全排列的同时去除重复元素的问题,提供了一种在递归过程中利用字典记录已选择元素的方法,以提高效率。示例代码展示了如何在Python中实现这一算法,适用于处理包含重复元素的数列的全排列问题。

Given a collection of numbers, nums, that might contain duplicates, return all possible unique permutations in any order.
Example 1:

Input: nums = [1,1,2]
Output:
[[1,1,2],
[1,2,1],
[2,1,1]]

大致意思是在全排列的基础上去重,如果先得到所有全排列,再去重,这样的效率是极低的,也是通过不了的。比较好的方法是在全排列的过程中进行裁剪分支,将重复的分支去除掉。

先回顾一下全排列,它的思想是这样的:对于n个数进行全排列,对于第一个位置,它有n种选择,选完之后,还剩n-1个数,对于第二个位置,它有n-1种选择,以此类推,共有n!种排列。从算法设计上,肯定需要选择递归回溯算法。对于第i个位置,它有n-i种选择,我们依此将i之后(包括i)的元素与第i个元素交换,这种交换思想起到了给第i个位置选择n-i种元素的作用。比如:我们选择第i+1个元素与第i个元素交换,然后通过递归进入后续的排列,当后续的排列完成时,通过再次交换回到之前状态,然后才可以选择第i+2个元素,重复以上过程。
参考代码:

def permute(self, nums: list):
        def mySwap(nums, left, right):
            temp = nums[left]
            nums[left] = nums[right]
            nums[right] = temp

        def permute_reverse(nums, begin, end, res):
           
            if (begin == end):
                res.append(list(nums))
            else:
                for i in range(begin,end):
                    mySwap(nums, i, begin)
                    permute_reverse(nums, begin + 1, end, res)
                    mySwap(nums, i, begin)
        res = []
        permute_reverse(nums, 0, len(nums), res)
        return res

如果能理解全排列的思想的话,理解全排列去重也就轻松多了,我接着上面的讲,对第i个位置元素的选择,如果我们选择了重复的元素的话,那最终的排列就会重复,要解决这种问题,我们只对每种元素选择一次就好了,也就是说对于(n-i)个候选元素,对其去重,可以把它当作字典或set集。
参考代码:

def permuteUnique(self, nums: list):
        def mySwap(nums, left, right):
            temp = nums[left]
            nums[left] = nums[right]
            nums[right] = temp

        def permute_reverse(nums, begin, end, res):
            process = dict()
            if (begin == end):
                res.append(list(nums))
            else:
                for j in range(begin,end):
                    if nums[j] not in process:
                        process[nums[j]]=1
                        mySwap(nums, j, begin)
                        permute_reverse(nums, begin + 1, end, res)
                        mySwap(nums, j, begin)
        res = []
        #nums.sort()
        permute_reverse(nums, 0, len(nums), res)
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值