力扣每日一题:回溯解法 全排列I & II

简介: 力扣每日一题:回溯解法 全排列I & II

46.全排列


https://leetcode-cn.com/problems/permutations/

难度:中等


题目:

给定一个 没有重复 数字的序列,返回其所有可能的全排列。


示例:

示例:

输入: [1,2,3]

输出:

[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]


分析

遇到全排列,所有可能等关键字,我们需要考虑DFS、回溯等解法。

这道题算是比较基础的题目,提供两种解法:

  1. python内置函数
  2. DFS 深度优先解题


解题1 内置函数:

from itertools import permutations
class Solution:
    def permute(self, nums):
        return list(permutations(nums))


解题2 DFS:

class Solution:
    def permute(self, nums):
        ret = []
        path = []
        def dfs(li):
            if len(li) == len(path):
                ret.append(path[:])
            for i in li:
                if i not in path:
                    path.append(i)
                    dfs(li)
                    path.pop()
        dfs(nums)
        return ret


47.全排列II


https://leetcode-cn.com/problems/permutations-ii/

难度:中等


题目:

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

提示:

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


示例:

示例 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]]


分析

这道题是 46.全排列的进阶版本。

当然,我们可以通过稍微修改46题的临时存储格式,来暴力AC这道题,如解法一。

但解法一种只是进行了单纯的回溯,在剪枝方面做得很不好,多出了很多不必要的循环,导致执行时间较长。

那么,针对不重复的序列,我们应该如何操作呢?

我们只需要对数组进行排序后,多使用一个列表用于记录该数组的数字是否使用过即可。


解题1 暴力回溯:

class Solution:
    def permuteUnique(self, nums):
        ret = []
        path = {}
        def dfs(li):
            if len(li) == len(path) and list(path.values()) not in ret:
                ret.append(list(path.values()))
            for i in range(len(li)):
                if i not in path:
                    path[i] = li[i]
                    dfs(li)
                    path.pop(i)
        dfs(nums)
        return ret


解题2 合理剪枝:

class Solution:
    def permuteUnique(self, nums):
        ret = []
        nums.sort()
        stage = [0 for _ in nums]
        path = []
        def dfs(li):
            if len(li) == len(path):
                ret.append(path[:])
                return
            for i in range(len(li)):
                if stage[i] == 1:
                    continue
                if i > 0 and li[i] == li[i - 1] and stage[i - 1] == 0:
                    continue
                path.append(li[i])
                stage[i] = 1
                dfs(li)
                path.pop()
                stage[i] = 0
        dfs(nums)
        return ret




相关文章
|
1月前
|
算法
Leetcode第46题(全排列)
这篇文章介绍了LeetCode第46题“全排列”的解题方法,使用深度优先搜索(DFS)和回溯算法来生成给定数组的所有可能排列。
26 0
Leetcode第46题(全排列)
|
1月前
Leetcode第47题(全排列II)
LeetCode第47题要求返回一个包含重复数字序列的所有不重复全排列,通过深度优先搜索和去重策略来解决。
29 0
|
3月前
|
算法
LeetCode第46题全排列
LeetCode第46题"全排列"的解题方法,利用回溯法避免重复并确保元素的有序性,生成所有可能的排列组合。
LeetCode第46题全排列
|
3月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
52 6
|
3月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
50 1
|
3月前
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
61 1
|
3月前
|
算法
LeetCode第47题全排列II
LeetCode第47题"全排列II"的解题方法,通过排序和添加去重逻辑,使用回溯法避免生成重复的排列组合。
|
3月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
55 0
|
3月前
|
存储 算法 Java
LeetCode初级算法题:两数之和+斐波拉契数列多种java解法
LeetCode初级算法题:两数之和+斐波拉契数列多种java解法
39 0
|
3月前
|
Python
【Leetcode刷题Python】46. 全排列
本文介绍了LeetCode题目46的Python编程解决方案,题目要求给定一个不含重复数字的数组,返回该数组所有可能的全排列。
25 0