请先做前置题目「NC43 没有重复项数字的全排列」。
本题和上一题的区别是数组中“存在重复元素”。当数组存在重复元素时,排列方案中也存在重复的排列方案。
为了排除这些重复方案,需在固定某位元素时,保证“每种元素只在此位固定一次”,即遇到重复元素时不交换,直接跳过,从而将生成重复排列的搜索分支进行“剪枝” 。
递归解析:
- 终止条件: 当 x = len(nums) - 1 时,代表所有位已固定(最后一位只有 1 种情况),则将当前组合 nums 转化为数组并加入 res ,并返回。
- 递推参数: 当前固定位 x 。
- 递推工作: 初始化一个 Set ,用于排除重复的元素;将第 x 位元素与 i ∈ [x, len(nums)] 元素分别交换,并进入下层递归。
- 剪枝: 若 nums[i] 在 Set 中,代表其是重复元素,因此 “剪枝” 。
- 将 nums[i] 加入 Set ,以便之后遇到重复元素时剪枝。
- 固定元素: 将元素 nums[i] 和 nums[x] 交换,即固定 nums[i] 为当前位元素。
- 开启下层递归: 调用 dfs(x + 1) ,即开始固定第 x + 1 个元素。
- 还原交换: 将元素 nums[i] 和 nums[x] 交换(还原之前的交换)。
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param num int整型一维数组
# @return int整型二维数组
#
class Solution:
def permuteUnique(self, num: List[int]) -> List[List[int]]:
# write code here
def dfs(x):
if x == len(num) - 1:
ans.append(num[:]) # 添加排列方案
return
dic = set()
for i in range(x, len(num)):
if num[i] in dic:
continue # 重复,因此剪枝
dic.add(num[i])
num[i], num[x] = num[x], num[i] # 交换,将 nums[i] 固定在第 x 位
dfs(x + 1) # 开启固定第 x + 1 位元素
num[i], num[x] = num[x], num[i] # 恢复交换
ans = []
dfs(0)
return sorted(ans) # 注意排序,否则提交可能不通过



京公网安备 11010502036488号