IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> python 回溯法生成全排列 -> 正文阅读

[数据结构与算法]python 回溯法生成全排列

问题:给定一个不含重复数字的数组?nums?,返回其?所有可能的全排列?。你可以?按任意顺序?返回答案。

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

回溯法

? ? ? ? 回溯算法其实是一种穷举的搜索方法,利用回溯解决问题就是在穷举所有的可能,然后找到我们想要的答案。使用回溯算法时需要考虑如下的三个问题:
????(1) 可选列表:所有可作出的选择;
????(2) 已选列表:也就是之前已经做出的选择;
????(3) 结束条件:当已选列表满足题目条件,可以结束穷举;

python 回溯算法框架

def backtrack(选择列表,路径):
    if 终止条件:
        存放结果
        return 
    for 选择 in 选择列表(本层集合中元素):
        处理节点
        backtrack(选择列表,路径)
        回溯,撤销处理结果

生成全排列算法1:

? ? ? ? 我们可以将题目给定的 n 个数的数组 nums 划分成左右两个部分,左边的表示已经填过的数,右边表示待填的数,我们在回溯的时候只要动态维护这个数组即可。

? ? ? ? 具体来说,假设我们已经填到第 first 个位置,那么 nums 数组中 [0,first ? 1] 是已填过的数的集合,[first , n - 1] 是待填的数的集合。我们肯定是尝试用 [first , n - 1]里的数去填第 first 个数,假设待填的数的下标为 i,那么填完以后我们将第 i?个数和第 first 个数交换,即能使得在填第 first + 1 个数的时候 nums 数组的 [0 , first] 部分为已填过的数,[first + 1,n ? 1] 为待填的数,回溯的时候交换回来即能完成撤销操作。

? ? ? ? 如图,每个树状节点是已填过的数(个数为first+1个)的集合,而该节点的子节点则是将待填的数的集合通过两个数元素的交换来填写第 first 个数。如[1,2,3,4],假设已经填到了第3个位置,[2,4]已填入,则该节点目前状态为[2,4 | 1,3]。假设需要填入3这个元素,我们则对1和3进行交换,first指针右移一位,变成[2,4,3 | 1]状态。

import copy
from typing import List

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def backtrack(n: int, nums: [int], res: List[List[int]], first: int):
            if first == n:
                c = copy.copy(nums)
                res.append(c)  # 需要深拷贝
            for i in range(first, n):
                nums[i], nums[first] = nums[first], nums[i]
                backtrack(n, nums, res, first + 1)
                nums[i], nums[first] = nums[first], nums[i]

        res = []
        backtrack(len(nums), nums, res, 0)
        return res

s = Solution()
print(s.permute([1, 2, 3]))

注意:其中res.append(c)需要用深拷贝,将nums当前的值赋给c,不然res.append存储的是nums的指针,最后res队列的若干结果都会相同。

生成全排列算法2:

排列问题与算法1不同:

? ? ? ? 1、每层都是从0开始搜索而不是first;
? ? ? ? 2、需要对新元素是否在path数组里做判断;

from typing import List

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res = []  # 存放符合条件结果的集合
        path = []  # 用来存放符合条件的结果

        def backtrack(nums):
            if len(path) == len(nums):
                return res.append(path[:])  # 此时说明找到了一组,此处为深拷贝
            for i in range(0, len(nums)):
                if nums[i] in path:  # path里已经收录的元素,直接跳过
                    continue
                path.append(nums[i])
                backtrack(nums)  # 递归
                path.pop()  # 回溯

        backtrack(nums)
        return res

s = Solution()
print(s.permute([1, 2, 3]))

注意:res.append(path[:]) 此处为深拷贝,若改成res.append(path),则结果为 [[], [], [], [], [], []] ,因为此时res中均为指向path的指针,而path中的值全部被pop。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 19:09:52  更:2022-07-20 19:10:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:36:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码