每天一道算法题:47. 全排列 II

难度

中等

题目

给定一个可包含重复数字的序列 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]]

提示:

1 <= nums.length <= 8
-10 <= nums[i] <= 10

思路

和 46 题类似但是不能有重复的解,46是数组中的元素各不相,不需要考虑重复元素,直接进行全排列。
47是数组中的元素可能包含重复,为了避免生成重复的全排列,需要在回溯的过程中跳过相邻的重复元素。数组中可能出现重复的数字,但是结果中不能出现重复的解,在处理过程中就要进行去重和剪枝。
首先对 nums 数组进行排序,在递归的过程中,添加了一个额外的集合 position 来跟踪已经选择的元素,并在回溯过程中进行去重的操作。

代码

from typing import List

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 先排序,让重复的数在一块
        self.nums = sorted(nums)
        self.result = []
        self.length = len(self.nums)
        self.position = [False] * self.length

        self.backtrack([])
        return self.result

    def backtrack(self, tmp):
        if len(tmp) == len(self.nums):
            self.result.append(tmp[:])
            return

        for i in range(len(self.nums)):
            # 当前元素与上一位元素相同,并且上一位元素已经用过了 就跳过, 层 去重复
            if i > 0 and self.nums[i] == self.nums[i - 1] and self.position[i - 1]:
                continue
            # 如果当前的元素已经用过了,就跳过 枝去重
            if self.position[i]:
                continue

            tmp.append(self.nums[i])
            self.position[i] = True
            self.backtrack(tmp)
            tmp.pop()
            self.position[i] = False

if __name__ == '__main__':
    nums = [1, 1, 2]
    s = Solution()
    s.subsets(nums)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骇客567

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值