【leetcode-Python】-回溯-47 Permutations II

这篇博客主要介绍了LeetCode中的47题Permutations II,这是一个关于数组排列的问题,允许重复元素。博主通过深度优先搜索(DFS)和回溯法两种方式给出了Python解决方案,详细解释了解题思路,如何处理重复元素以避免生成重复的排列,并提供了示例代码。
摘要由CSDN通过智能技术生成

 

目录

 

题目链接

题目描述

示例

解决思路一

Python实现

解题思路二


题目链接

47 Permutations II

题目描述

给定一系列数字组成的列表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
            
        

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值