Leetcode每日一题2021/02/09

Leetcode每日一题2021/02/09_第1张图片

# 方法一(在最后判断有无重复元素,这样操作会导致很多重复的计算)
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        res = []
        self.backTrack(n, 0, nums, res)
        return res

    def backTrack(self, n, first, nums, res):
        if(first == n and nums[:] not in res):
            res.append(nums[:])
        for i in range(first, n):
            nums[first], nums[i] = nums[i], nums[first]
            self.backTrack(n, first+1, nums, res)
            nums[first], nums[i] = nums[i], nums[first]

Leetcode每日一题2021/02/09_第2张图片

Leetcode每日一题2021/02/09_第3张图片

  • 参考sammy的题解。
# 方法二(进行剪枝,减少计算量)
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        res = []
        nums.sort()             # 排序是剪枝的前提,否则nums[i] == nums[i-1]这个判断就会出问题,会漏掉元素
        used = [0] * n          # used数组表示被使用的元素
        self.backTrack(n, [], nums, res, used)
        return res

    def backTrack(self, n, path, nums, res, used):
        if(len(path) == n):
            res.append(path.copy())
        for i in range(n):
            if(used[i] == 1):
                continue
            if(i > 0 and nums[i] == nums[i-1] and not used[i-1]):   # 前一个相同元素没被使用,当前的也不用
                continue                                            # 即,used[i-1] == 0不用
            used[i] = 1
            path.append(nums[i])
            self.backTrack(n, path, nums, res, used)
            used[i] = 0
            path.pop()

Leetcode每日一题2021/02/09_第4张图片
这是第一种方法的示意图。
经过分析,在这里不方便使用剪枝。
参考:LeetCode官方题解。
Leetcode每日一题2021/02/09_第5张图片
这是第二种方法的示意图。
蓝色框表示选择的路径元素,橙色框标识使用过的元素,红色表示被剪枝。
参考:liweiwei1419题解。
Leetcode每日一题2021/02/09_第6张图片
回溯算法是穷举所有情况,包含3个操作。
1.选择;(此题就是蓝色框Path的选择)
2.撤销;(此题就是used[i]=0,撤销选择操作)
3.结束条件。(len(path)==n是结束条件)

你可能感兴趣的:(Leetcode,python,leetcode,算法)