问题描述
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
给定一个可能包含重复元素的整数数组 nums
,编写一个函数来返回所有不重复的全排列
示例 1:
输入:nums = [1,1,2] 输出: [[1,1,2],[1,2,1],[2,1,1]]
示例 2:
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
解题思路: 回溯 剪枝
这个问题可以使用回溯算法来解决。回溯算法是一种通过穷举所有可能情况来找到所有解的算法。在这个问题中,我们需要通过回溯来生成所有可能的排列,并且在生成排列的过程中,需要保证排列中不存在重复元素。
具体实现时,可以定义一个递归函数 backtrace()
来进行回溯。该函数接受五个参数:
res
: 用于存储所有不重复的排列nums
: 给定的整数数组check
: 标记数组,用于记录每个元素是否已经使用过element
: 当前正在生成的排列depth
: 当前正在考虑的元素的下标
在递归函数 backtrace()
中,我们首先判断当前排列是否已经包含了所有的元素。如果是,就将当前排列添加到结果列表 res
中,然后返回。
如果当前排列还没有包含所有的元素,就从给定的整数数组 nums
中选择一个未使用过的元素,并将其添加到当前排列 element
中。接着,我们递归调用 backtrace()
函数,继续向后生成排列。当递归返回时,我们需要将当前加入的元素从排列中删除,并将其标记为未使用过,以便后续的排列生成。
在生成排列的过程中,我们需要注意避免重复排列的情况。具体来说,如果当前元素和前一个元素相同,并且前一个元素还没有被使用过,就应该跳过当前元素,以避免生成重复排列。
最后,我们调用 backtrace()
函数,将结果列表 res
返回即可。
代码实现
下面是 Python 代码实现。其中,backtrace()
函数就是上述的递归函数,它通过检查当前元素是否和前一个相同来避免重复排列的情况。
class Solution:def permuteUnique(self, nums: List[int]) -> List[List[int]]:nums.sort()res = []element = []check = [0 for _ in range(len(nums))]depth = 0def backtrace(res, nums, check,element, depth):if depth == len(nums):res.append(element[:])returnfor i in range(len(nums)):if check[i] == 0:# 防止重复:if i >0 and nums[i] == nums[i-1] and check[i-1] == 0:continuecheck[i] = 1element.append(nums[i])backtrace(res, nums, check, element, depth+1)check[i] = 0element.pop()backtrace(res, nums, check, element, depth)return res
总结
「全排列 II」问题是一道经典的回溯算法问题。在解决这个问题的过程中,我们需要通过回溯来生成所有可能的排列,并且在生成排列的过程中,需要保证排列中不存在重复元素。具体实现时,可以定义一个递归函数 backtrace()
来进行回溯,并通过检查当前元素是否和前一个相同来避免重复排列的情况。
回溯问题三要素:
#### 有效结果
if len(sol) == len(nums):
#### 回溯范围及答案更新
check[i] = 1element.append(nums[i])backtrace(res, nums, check, element, depth+1)check[i] = 0element.pop()
#### 剪枝条件
if check[i] == 1:continue
if i > 0 and nums[i] == nums[i-1] and check[i-1] == 0:continue