【算法】(Python)回溯算法

回溯算法:

  • 回溯算法是一种算法思想。
  • 采用“深度优先搜索(dfs,depth first search)”。
  • 采用“尝试”和“回溯”的策略。尝试搜索所有可能的解决方案,遇到不满足条件的撤销选择、回退到回溯点(满足回溯条件的某个状态的点)、尝试其他方法。
  • 基本思想:从一条路往前走,能进则进,不能进则退回来,换条路再试。
  • 类似穷举法,但有剪枝的功能。剪枝:去除不满足约束条件的尝试、提高效率。
  • 通常用递归实现。(也可以用迭代实现,但设计复杂)

回溯算法的伪代码模板:

res = []                                 # 记录所有的最终解

def traceback(各参数):

    if 终止条件:
        res.append(最终解)                # 保存结果
        return

    for 方案 in 所有可能的解决方案:          # 遍历所有可能的解决方案
        if 约束条件:                       # 剪枝
            做出选择,更新状态
            traceback(各参数)              # 递归搜索
            回溯,撤销选择,回退到上一状态


traceback(各参数)                          # 执行函数

举例:

1、(难度:简单)【力扣】1863. 找出所有子集的异或总和再求和

解题思路:搜索所有组合,深度优先搜索。遍历给定列表中每个元素,选择该元素并往下递归搜索,再撤销选择,尝试其他搜索。最后所有组合的异或结果求和。

知识点:x ^ y:x和y进行异或运算。异或运算:二进制中各位依次比对,相同为0,不同为1。 

class Solution:
    def subsetXORSum(self, nums: List[int]) -> int:
        
        def traceback(i, xor):
            # 终止条件:遍历到列表结束
            if i == n:
                res.append(xor)      # 最终解保存到结果列表中
                return
            
            # 选择当前元素
            traceback(i + 1, xor ^ nums[i])
            # 撤销选择(即不选择当前元素)
            traceback(i + 1, xor)

        res = []            # 结果列表,存放所有组合的异或结果
        xor = 0             # 一个组合的异或结果
        i = 0               # 目前是列表中哪个元素
        n = len(nums)       # 列表长度

        traceback(i, xor)   # 执行函数
        return sum(res)

2、(难度:中等)【力扣】46. 全排列

 解题思路:全排列:每个元素都有,只是顺序不同。因此,两个列表:结果列表(存放所有组合),存放一个全排列组合的列表。依次往组合中添加元素,给定列表中的每个元素只添加一次。添加元素时,每次从头遍历给定列表,分别选择该元素或不选择该元素。搜索所有组合。

知识点:res.append(alist[:]):往结果列表res中添加列表alist。需使用alist[:],否则回溯时pop撤销选择时,列表alist中会删除最后一个元素,结果列表res中也会删除该元素,最终结果则为空列表。

              alist.pop():删除列表alist中最后一个元素。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        
        def traceback(index):
            # 终止条件:列表遍历结束
            if index == n:
                res.append(alist[:])        # 结果列表中保存组合
                return

            # 全排列(每个元素都有,只是顺序不同),每次从头遍历
            for i in range(0, n):
                # 每个元素在组合中只能出现一次
                if nums[i] not in alist:
                    # 选择当前元素
                    alist.append(nums[i])
                    traceback(index + 1)     # 递归,往下继续添加元素
                    # 撤销选择(即不选择当前元素)
                    alist.pop()

        res = []            # 结果列表,存放所有全排列的组合
        alist = []          # 一个全排列的组合
        index = 0           # 在组合中添加到哪个元素
        n = len(nums)       # 列表长度

        traceback(index)    # 执行函数
        return res

3、(难度:困难)【力扣】51. N 皇后

(3-1)使用集合

解题思路:皇后所在位置不能同一行、同一列、不能在两个斜线位置(左上到右下,右上到左下)。因此,三个集合:存放皇后所在列号,两个斜线(左上到右下,行号和列号的差相同。右上到左下,行号和列号的和相同)。搜索每一行皇后所在位置,尝试所有可能结果。

知识点: [ ]:空列表。列表:元素可重复的有序、可变的序列。

               列表.append(元素):往列表添加元素。

               列表[下标]:获取或修改列表下标对应的元素。

               "间隔符".join(列表):列表中所有元素按照指定间隔符组合成字符串。间隔符可以为空。

               [元素] * n:列表,列表中有n个相同的指定元素。

               set( ):空集合。集合:元素不重复的无序、可变的序列。

               集合.add(元素):往集合添加元素。

               集合.remove(元素):从集合删除元素。

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def trackback(rowindex):
            # 终止条件:棋盘所有行遍历结束
            if rowindex == n:
                board = []                          # 棋盘列表,存放整个棋盘内容
                for i in range(n):
                    row[queen[i]] = "Q"             # 各行皇后所在的列下标对应元素为Q
                    board.append("".join(row))      # 各行加入棋盘
                    row[queen[i]] = "."             # 恢复行初始值
                res.append(board)                   # 结果列表记录最终整个棋盘
                return
            
            # 遍历棋盘所有列
            for colindex in range(n):
                # 判断:不与皇后同一列、斜线(左上到右下,行号与列号的差相同。右上到左下,行号与列号的和相同)
                if colindex not in columns \
                and colindex - rowindex not in diagonal_1 \
                and colindex + rowindex not in diagonal_2:
                    # 选择该位置为皇后
                    queen[rowindex] = colindex
                    columns.add(colindex)
                    diagonal_1.add(colindex - rowindex)
                    diagonal_2.add(colindex + rowindex)
                    trackback(rowindex + 1)            # 递归搜索
                    # 撤销选择(即该位置不为皇后)
                    columns.remove(colindex)
                    diagonal_1.remove(colindex - rowindex)
                    diagonal_2.remove(colindex + rowindex)
        
        res = []                # 结果列表,存放所有最终棋盘结果
        columns = set()         # 集合,存放所有皇后所在的列下标
        diagonal_1 = set()      # 集合,存放所有皇后的斜线(左上到右下)
        diagonal_2 = set()      # 集合,存放所有皇后的斜线(右上到左下)
        queen = [-1] * n        # 皇后列表,皇后初始值,存放每行皇后所在的列下标
        row = ['.'] * n         # 行列表,行初始值
        rowindex = 0            # 目前在哪一行

        trackback(rowindex)     # 执行函数
        return res

(3-2)使用二进制

解题思路:将棋盘每行视为一串二进制,尝试所有可能的位置。第一行从最右边(低位)开始搜索,获取皇后所在位置在棋盘上该行的列下标。下一行,新皇后不能同一列,不能斜线(即可能位置为左侧斜线右移一位,右侧斜线左移一位),继续搜索,搜索所有行的皇后位置。再新一轮搜索第一行下一个可能位置,依次类推,深度优先搜索,搜索所有可能结果。

知识点:1 << n:1左移n位。若n=4,则二进制10000。

             (1 << n)-1:若n=4,则结果为二进制1111。即棋盘中一行4位均为可能位置。

             (~(columns | diagonal_1 | diagonal_2):“|”即or,“~”为取反。即不与已有皇后同一列、两个斜线位置。

              may_pos & (-may_pos) : 获取二进制may_pos中最右边为1的位置,即皇后可能位置。

              may_pos & (may_pos - 1) :将二进制may_pos最右边的1置为0,即剩余可能位置。

              bin(...).count("1"):统计二进制中1的个数。以次获取列下标。

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def trackback(rowindex, columns, diagonal_1, diagonal_2):
            # 终止条件:遍历棋盘所有行
            if rowindex == n:
                board = []                      # 保存整个棋盘内容
                for i in range(n):
                    row[queen[i]] = "Q"         # 皇后所在位置元素为Q
                    board.append("".join(row))  # 保存各行
                    row[queen[i]] = "."         # 行恢复初始值
                res.append(board)               # 结果列表中保存最终整个棋盘
                return
            
            # 所有可能的位置
            may_pos = ((1 << n) - 1) & (~(columns | diagonal_1 | diagonal_2))
            # 遍历所有可能的位置
            while may_pos:
                pos = may_pos & (-may_pos)            # 获取最右边为1的位置
                colindex = bin(pos - 1).count("1")    # 最右边1的位置转为在棋盘中的列下标
                queen[rowindex] = colindex            # 保存该行皇后的列下标
                may_pos = may_pos & (may_pos - 1)     # 将最右边的1置为0,剩余可能位置
                # 递归搜索
                trackback(rowindex + 1, columns | pos, (diagonal_1 | pos) << 1, (diagonal_2 | pos) >> 1)

        res = []                # 结果列表,保存所有的最终棋盘
        queen = [-1] * n        # 存放各行皇后所在的列下标
        row = ["."] * n         # 行初始值
        # 目前所在行号、列号、两个斜线位置
        rowindex, columns, diagonal_1, diagonal_2 = 0, 0, 0, 0

        trackback(rowindex, columns, diagonal_1, diagonal_2)
        return res

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904854.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

音视频入门基础:FLV专题(18)——Audio Tag简介

一、引言 根据《video_file_format_spec_v10_1.pdf》第75页&#xff0c;如果某个Tag的Tag header中的TagType值为8&#xff0c;表示该Tag为Audio Tag&#xff1a; 这时StreamID之后紧接着的就是AudioTagHeader&#xff0c;也就是说这时Tag header之后的就是AudioTagHeader&…

探索Python终端美化的终极利器:Rich库

文章目录 &#x1f680; 探索Python终端美化的终极利器&#xff1a;Rich库第一部分&#xff1a;背景介绍第二部分&#xff1a;Rich库是什么&#xff1f;第三部分&#xff1a;如何安装Rich库&#xff1f;第四部分&#xff1a;Rich库的简单函数使用方法第五部分&#xff1a;结合场…

【Java笔记】1-JDK/JRE/JVM是个啥?

JDK、JRE、JVM可以说是入门必须了解的三个词汇 先说全称 JDK&#xff1a;Java Development Kit&#xff0c;Java开发工具包 JRE&#xff1a;Java Runtime Environment&#xff0c;Java运行环境 JVM&#xff1a;Java Virtual Machine&#xff0c;Java虚拟机 再说关系 JVM⊆J…

视觉目标检测标注xml格式文件解析可视化 - python 实现

视觉目标检测任务&#xff0c;通常用 labelimage标注&#xff0c;对应的标注文件为xml。 该示例来源于开源项目&#xff1a;https://gitcode.com/DataBall/DataBall-detections-100s/overview 读取 xml 标注文件&#xff0c;并进行可视化示例如下&#xff1a; #-*-coding:ut…

金和OA-C6 ApproveRemindSetExec.aspx XXE漏洞复现(CNVD-2024-40568)

0x01 产品描述&#xff1a; 金和C6协同管理平台是以"精确管理思想"为灵魂&#xff0c;围绕“企业协同四层次理论”模型&#xff0c;并紧紧抓住现代企业管理的六个核心要素&#xff1a;文化 Culture、 沟通Communication 、 协作Collaboration 、创新 Creation、 控制…

ETL集成工具丨如何运用ETLCloud单步调试断点功能

在现代数据处理领域&#xff0c;ETLCloud 的单步调试断点功能正成为数据管理的重要工具。ETLCloud 是一个强大的云端数据处理平台&#xff0c;它提供了灵活的单步调试功能&#xff0c;使得用户能够逐步跟踪和分析数据处理流程。本文将探讨如何运用 ETLCloud 的单步调试断点功能…

GB/T 28046.2-2019 道路车辆 电气及电子设备的环境条件和试验 第2部分:电气负荷(3)

写在前面 本系列文章主要讲解道路车辆电气及电子设备的环境条件和试验GB/T 28046标准的相关知识&#xff0c;希望能帮助更多的同学认识和了解GB/T 28046标准。 若有相关问题&#xff0c;欢迎评论沟通&#xff0c;共同进步。(*^▽^*) 第2部分&#xff1a;电气负荷 4.9 抛负载…

开源陪玩系统平台源码-支持游戏线上陪玩家政线下预约等多场景应用支持H5+小程序+APP

陪玩平台的流行可以归因于多个因素&#xff0c;包括现代生活的快节奏和压力、电竞行业的带动、孤独经济的兴起&#xff0c;以及技术的进步等。这些因素共同推动了陪玩平台的发展&#xff0c;使其成为人们寻求社交互动和休闲娱乐的重要途径。 现代生活的快节奏和压力 现代生活…

1:基本电路专题:R(电阻)的介绍

说实话这个其实我不想写的&#xff0c;因为这个是初中的知识&#xff0c;并没有很难&#xff0c;但是为了保持整齐性&#xff0c;我还是写了一下关于这个的知识点。是电子学中三大基本无源元件之一。&#xff08;R&#xff08;电阻&#xff09;,L&#xff08;电感&#xff09;,…

解决注册Kaggle出现的“Captcha must be filled out”问题

首先&#xff0c;出现这个问题后&#xff0c;就搜索了一下别的博主的方法。 使用header editor 插件 首先&#xff0c;下载扩建&#xff1a; 然后进行重定向&#xff1a; 管理之后&#xff0c;输入下面的地址&#xff0c;然后下载-保存&#xff1a; 但是&#xff0c;这条显然…

大模型面试题持续更新_Moe(2024-10-30)

扫一扫下方&#xff0c;获取更多面试真题的集合 Moe和集成学习方法有什么异同&#xff1f; MoE和集成学习的思想异曲同工&#xff0c;都是集成了多个模型的方法&#xff0c;Moe主要是将预测任务分为多个子任务&#xff0c;然后通过路由网络的形式决定对于当前的数据该使用哪个…

Vue-$el属性

原博客地址&#xff1a;深入 Vue.js 的心脏&#xff1a;全面剖析 $el 属性_vue $el-CSDN博客 目录 1 $el是什么 1.1 $el本质 1.2 访问$el时机 1.3 $el与模板的关系 2 $el使用场景 2.1 集成第三方库 2.2 操作DOM元素样式 2.3 处理焦点和事件 2.4 实现自定义指令 3 $e…

小满OKKICRM与钉钉数据集成方案解析

小满-宜搭产品同步&#xff1a;小满OKKICRM数据集成到钉钉的技术实现 在企业信息化建设中&#xff0c;系统间的数据集成是提升业务效率和数据一致性的关键环节。本文将聚焦于“小满-宜搭产品同步”方案&#xff0c;详细探讨如何将小满OKKICRM的数据高效、可靠地集成到钉钉平台…

【prefect】Prefect二:python任务调度工具 Prefect 基础使用教程 | work pool | Deployment | flow

一、Work Pool 1、什么是 Work Pool 白话解释&#xff1a;集中管理部署脚本的开关 Work pools allow you to switch between different types of infrastructure and to create a template for deployments. Data platform teams find work pools especially useful for mana…

蓝海创意云入选中国夏衍电影学会工业与科技影视专业委员会成员单位

党的二十届三中全会指出&#xff0c;科技自立自强是中国式现代化的有力保障。科技兴则民族兴&#xff0c;科技强则国家强。为深入的贯彻落实这一重要部署&#xff0c;推动工业与科技领域的融合发展充分发挥电影艺术在传播科技创新精神、展现工业发展成就方面的独特作用&#xf…

基于SpringBoot的“CSGO赛事管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“CSGO赛事管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统首页界面图 赛事信息界面图 赛事通知界面…

WPF+MVVM案例实战(十三)- 封装一个自定义消息弹窗控件(上)

文章目录 1、案例效果2、功能实现1、创建文件2、资源文件获取3、枚举实现3、弹窗实现1、界面样式实现2、功能代码实现4、总结1、案例效果 2、功能实现 1、创建文件 打开 Wpf_Examples 项目,我们在用户控件类库中创建一个窗体文件 SMessageBox.xaml,同时创建枚举文件夹 Enum…

室内障碍物射线追踪算法matlab模拟仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 增加发射点 加入室内墙壁&#xff1a; 同时增加发射点和室内墙壁&#xff1a; 2.算法运行软件版本 matlab2022a 3.部分…

荒野大镖客:救赎 PC版整合包

游戏名称&#xff1a;荒野大镖客&#xff1a;救赎 英文名称&#xff1a;Red Dead Redemption 游戏类型&#xff1a;动作冒险类(ACT)游戏 游戏制作&#xff1a;Rockstar Games/Double Eleven 游戏发行&#xff1a;Rockstar Games 游戏平台&#xff1a;PC 发售时间&#xff1a;20…

ubuntu双屏只显示一个屏幕另一个黑屏

简洁的结论&#xff1a; 系统环境 ubuntu22.04 nvidia-535解决方案 删除/etc/X11/xorg.conf 文件 记录一下折腾大半天的问题。 ubuntu系统是22.04,之前使用的时候更新驱动导致桌面崩溃&#xff0c;重新安装桌面安装不上&#xff0c;请IT帮忙&#xff0c;IT一番操作过后也表示…