当前位置: 首页 > article >正文

Python算法基础篇之深度优先搜索(DFS)

一、什么是深度优先搜索DFS深度优先搜索Depth-First Search, DFS是一种用于遍历或搜索图、树的算法。其核心策略是从起始节点出发沿着一条路径尽可能深入地探索直到无法继续为止然后回溯到上一个节点继续探索其他分支。1.1 核心思想三步走深入从起始节点出发沿着一条路径一直走到尽头回溯遇到死胡同无未访问邻居时退回上一个节点重复继续探索其他分支直到所有节点都被访问1.2 形象比喻想象你在一个巨大的迷宫中探险你总是选择一条岔路一直走到底遇到死路就原路返回到上一个岔路口选择另一条没走过的岔路继续探索直到走遍迷宫的每一个角落这就是DFS的精髓——“不撞南墙不回头”。1.3 DFS遍历过程图解下面是一张DFS遍历过程的示意图展示了DFS如何沿着一条路径深入探索如上图所示DFS从节点A出发优先选择一条路径深入A → C → B走到尽头后回溯再探索其他分支C → D → F → G → E。二、DFS的数据结构支撑栈StackDFS的实现依赖于栈Stack这种数据结构。2.1 栈的特性栈是一种后进先出LIFO, Last In First Out的数据结构最后放入的元素最先被取出就像一摞盘子只能从最上面取放2.2 DFS与栈的关系DFS有两种实现方式都与栈有关实现方式栈的类型特点递归实现系统调用栈隐式代码简洁但有递归深度限制非递归实现手动维护栈显式避免栈溢出适合大规模数据三、递归实现DFS3.1 图的DFS遍历递归版# 图的DFS遍历 - 递归实现defdfs_recursive(graph,start,visitedNone):ifvisitedisNone:visitedset()# 访问当前节点print(start,end )visited.add(start)# 递归访问所有未访问的邻居节点forneighboringraph.get(start,[]):ifneighbornotinvisited:dfs_recursive(graph,neighbor,visited)returnvisited# 构建示例图邻接表表示graph{A:[B,C],B:[A,D,E],C:[A,F,G],D:[B],E:[B,H],F:[C],G:[C],H:[E]}print(*50)print(【示例1】图的DFS递归遍历)print(*50)print(图结构:,graph)print( DFS遍历顺序从A开始:)visited_nodesdfs_recursive(graph,A)print(f 已访问节点:{visited_nodes})运行结果 【示例1】图的DFS递归遍历 图结构: {A: [B, C], B: [A, D, E], C: [A, F, G], D: [B], E: [B, H], F: [C], G: [C], H: [E]} DFS遍历顺序从A开始: A B D E H C F G 已访问节点: {A, B, D, E, H, C, F, G}关键点解析visited集合至关重要防止在图中形成无限循环因为图可能有环递归调用时系统自动使用调用栈来保存每层的状态遍历顺序取决于邻居列表的顺序3.2 二叉树的DFS遍历二叉树的DFS有三种经典遍历方式都是递归实现classTreeNode:def__init__(self,val0,leftNone,rightNone):self.valval self.leftleft self.rightright# 前序遍历根 → 左 → 右defdfs_preorder(root):ifrootisNone:returnprint(root.val,end )dfs_preorder(root.left)dfs_preorder(root.right)# 中序遍历左 → 根 → 右defdfs_inorder(root):ifrootisNone:returndfs_inorder(root.left)print(root.val,end )dfs_inorder(root.right)# 后序遍历左 → 右 → 根defdfs_postorder(root):ifrootisNone:returndfs_postorder(root.left)dfs_postorder(root.right)print(root.val,end )# 构建示例二叉树# 1# / \# 2 3# / \# 4 5rootTreeNode(1)root.leftTreeNode(2)root.rightTreeNode(3)root.left.leftTreeNode(4)root.left.rightTreeNode(5)print( *50)print(【示例2】二叉树的DFS三种遍历方式)print(*50)print(二叉树结构:)print( 1)print(/\)print( 2 3)print(/\)print( 4 5)print( 前序遍历根-左-右:,end )dfs_preorder(root)print( 中序遍历左-根-右:,end )dfs_inorder(root)print( 后序遍历左-右-根:,end )dfs_postorder(root)运行结果 【示例2】二叉树的DFS三种遍历方式 二叉树结构: 1 / 2 3 / 4 5 前序遍历根-左-右: 1 2 4 5 3 中序遍历左-根-右: 4 2 5 1 3 后序遍历左-右-根: 4 5 2 3 1三种遍历的应用场景遍历方式顺序典型应用前序遍历根-左-右复制二叉树、序列化中序遍历左-根-右二叉搜索树排序结果有序后序遍历左-右-根计算树高、删除树节点四、非递归实现DFS显式栈递归实现虽然简洁但当图/树很深时可能导致递归栈溢出RecursionError。非递归实现使用显式栈来避免这个问题。4.1 图的DFS非递归实现fromcollectionsimportdequedefdfs_iterative(graph,start):visitedset()stack[start]result[]whilestack:nodestack.pop()ifnodenotinvisited:visited.add(node)result.append(node)print(node,end )# 将邻居节点压入栈反转顺序以保持与递归一致forneighborinreversed(graph.get(node,[])):ifneighbornotinvisited:stack.append(neighbor)returnresultprint( *50)print(【示例3】图的DFS非递归遍历显式栈)print(*50)print(DFS遍历顺序从A开始:)dfs_resultdfs_iterative(graph,A)print(f 遍历结果列表:{dfs_result})运行结果 【示例3】图的DFS非递归遍历显式栈 DFS遍历顺序从A开始: A B D E H C F G 遍历结果列表: [A, B, D, E, H, C, F, G]非递归实现关键点使用list的append()和pop()模拟栈操作邻居节点需要反转顺序入栈才能保证与递归实现遍历顺序一致入栈时可以不检查是否已访问出栈时检查但入栈时检查效率更高五、DFS经典实战LeetCode 200. 岛屿数量5.1 题目描述给定一个由 ‘1’陆地和 ‘0’水组成的二维网格计算岛屿的数量。岛屿总是被水包围并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。5.2 解题思路这是DFS最经典的网格类应用遍历每个格子遇到’1’未访问的陆地就启动DFSDFS将所有相连的’1’标记为’0’沉岛策略每启动一次DFS岛屿数量15.3 代码实现defnumIslands(grid):ifnotgridornotgrid[0]:return0rows,colslen(grid),len(grid[0])count0defdfs(r,c):# 边界检查 水域检查递归终止条件ifr0orrrowsorc0orccolsorgrid[r][c]0:return# 标记当前陆地为已访问沉岛策略grid[r][c]0# 四个方向探索上、下、左、右directions[(-1,0),(1,0),(0,-1),(0,1)]fordr,dcindirections:dfs(rdr,cdc)# 遍历整个网格foriinrange(rows):forjinrange(cols):ifgrid[i][j]1:count1dfs(i,j)returncount# 测试用例grid1[[1,1,0,0,0],[1,1,0,0,0],[0,0,1,0,0],[0,0,0,1,1]]print( *50)print(【示例4】LeetCode 200: 岛屿数量DFS经典应用)print(*50)print(原始地图:)forrowingrid1:print(row)print(f 岛屿数量:{numIslands(grid1)})运行结果 【示例4】LeetCode 200: 岛屿数量DFS经典应用 原始地图: [1, 1, 0, 0, 0] [1, 1, 0, 0, 0] [0, 0, 1, 0, 0] [0, 0, 0, 1, 1] 岛屿数量: 3DFS网格类问题模板总结defdfs_grid(grid,r,c):# 1. 边界检查ifnot(0rlen(grid)and0clen(grid[0])):return# 2. 终止条件根据题目调整ifgrid[r][c]0:return# 3. 标记已访问grid[r][c]0# 4. 四个方向递归探索dfs_grid(grid,r-1,c)# 上dfs_grid(grid,r1,c)# 下dfs_grid(grid,r,c-1)# 左dfs_grid(grid,r,c1)# 右六、DFS进阶回溯与剪枝6.1 什么是回溯回溯是DFS的一种特殊应用用于搜索所有可能的解。当DFS走到死胡同时回溯到上一步尝试其他选择。6.2 组合总和问题带剪枝优化defcombination_sum(nums,target):result[]nums.sort()defbacktrack(start,current_sum,path):# 剪枝当前和已经超过target无需继续ifcurrent_sumtarget:return# 找到有效解ifcurrent_sumtarget:result.append(path[:])returnforiinrange(start,len(nums)):# 去重剪枝跳过重复元素ifistartandnums[i]nums[i-1]:continuepath.append(nums[i])backtrack(i,current_sumnums[i],path)path.pop()# 回溯撤销选择backtrack(0,0,[])returnresultprint( *50)print(【示例5】DFS回溯 剪枝优化)print(*50)nums[2,3,6,7]target7print(f数组:{nums}, 目标和:{target})print(f所有组合:{combination_sum(nums,target)})运行结果 【示例5】DFS回溯 剪枝优化 数组: [2, 3, 6, 7], 目标和: 7 所有组合: [[2, 2, 3], [7]]回溯算法框架defbacktrack(路径,选择列表):if满足结束条件:result.add(路径)returnfor选择in选择列表:做选择 backtrack(路径,选择列表)撤销选择# 回溯七、DFS常见陷阱与避坑指南7.1 陷阱1忘记标记已访问节点# 错误示例会导致无限循环defdfs_wrong(graph,start):print(start,end )forneighboringraph.get(start,[]):dfs_wrong(graph,neighbor)# 正确做法始终维护visited集合defdfs_correct(graph,start,visitedNone):ifvisitedisNone:visitedset()print(start,end )visited.add(start)forneighboringraph.get(start,[]):ifneighbornotinvisited:dfs_correct(graph,neighbor,visited)7.2 陷阱2递归深度过大importsys# Python默认递归深度限制为1000print(f默认递归深度限制:{sys.getrecursionlimit()})# 对于大规模数据需要提高限制sys.setrecursionlimit(10000)# 更好的方案使用非递归实现显式栈7.3 陷阱3网格DFS边界条件写错# 错误先标记再检查边界defdfs_bad(grid,r,c):grid[r][c]0dfs_bad(grid,r-1,c)# 正确先检查边界再标记defdfs_good(grid,r,c):ifr0orrlen(grid)orc0orclen(grid[0])orgrid[r][c]0:returngrid[r][c]0dfs_good(grid,r-1,c)八、DFS总结8.1 核心要点DFS 深度优先搜索 数据结构栈Stack/ 递归调用栈 核心策略纵向深入不撞南墙不回头 关键操作访问 - 递归深入 - 回溯 必备要素visited集合防循环 时间复杂度O(V E) 空间复杂度O(h)h为最大深度8.2 DFS适用场景场景说明连通性检测岛屿数量、朋友圈、连通分量拓扑排序课程表、任务调度全排列/组合子集、排列、组合总和路径搜索迷宫问题找任意路径树遍历前序、中序、后序遍历

相关文章:

Python算法基础篇之深度优先搜索(DFS)

一、什么是深度优先搜索(DFS)? 深度优先搜索(Depth-First Search, DFS) 是一种用于遍历或搜索图、树的算法。其核心策略是:从起始节点出发,沿着一条路径尽可能深入地探索,直到无法继…...

信创中间件深度解析:东方通TongWeb vs 金蝶天燕 vs 宝兰德,企业级选型指南

📚 信创中间件 🔧 企业级部署 🚀 国产化替代 ⏱️ 阅读约15分钟开篇导读:你是否在信创改造中不知道用什么替代WebLogic或WebSphere?网上搜到的中间件资料要么只讲产品功能不讲迁移方案,要么直接给配置却不解…...

中小企业AI落地成本杀手!DeepSeek计费冷知识曝光(含4个可立即启用的免费优化开关)

更多请点击: https://codechina.net 第一章:中小企业AI落地成本杀手!DeepSeek计费冷知识曝光(含4个可立即启用的免费优化开关) 很多中小企业误以为调用 DeepSeek API 的成本仅取决于 token 数量,却忽略了隐…...

网络技术05-TCP拥塞控制算法——从CUBIC到BBR的性能进化

🚗 一句话总结:TCP拥塞控制就像开车——看到前面堵车就减速(拥塞避免),路通畅了就慢慢加速(慢启动)。CUBIC是"看到堵车就猛踩刹车",BBR是"根据路况预测提前调整"…...

eClinMed 中国人民解放军总医院第五医学中心介入超声科:基于超声的可解释性机器学习模型用于≤3cm肝细胞癌分类的开发与验证

01文献信息本次分享的文献是由中国人民解放军总医院第五医学中心介入超声科联合厦门大学附属翔安医院、南开大学医学院和福州市第一总医院超声科等55家医院在2025年2月在柳叶刀子刊《eClinicalMedicine》(中科院1区,IF10.0)上的研究“Develop…...

J Thorac Oncol(IF=20.8)广东省人民医院钟文昭教授团队:基于影像组学的支持向量机区分驱动肺腺癌进展的分子事件

01文献信息本次分享的文献是由广东省人民医院肺癌研究所钟文昭教授团队联合华南理工大学医学院、广东省人民医院病理科、核医学科等多学科团队在2024年9月19日在《Journal of Thoracic Oncology》(中科院1区,IF20.8)上发表的研究“Radiomics-…...

Claude Code 2026 全命令实战:6分钟开发完整坦克对战游戏

文章目录前言第一步:新建文件夹,然后输入一个单词第二步:/plan命令,比产品经理还贴心的规划师第三步:看着AI写代码,自己在旁边喝咖啡第四步:/rewind命令,程序员的后悔药第五步&#…...

深度剖析Claude Code实操逻辑,解锁AI编程高效开发方式

文章目录前言一、我用Claude Code的翻车现场,能写一本《程序员血泪史》二、Claude Code的核心设计思想:你以为它是保姆,其实它是保安三、普通模式vs规划模式:一个是临时工,一个是项目经理四、两条核心指令,…...

掌握AI技能配置技巧 大幅提升日常办公开发效率

P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能…...

量子机器学习模型安全:反向工程威胁与防御策略解析

1. 量子机器学习模型的反向工程:安全威胁与防御策略量子计算与机器学习的结合,正以前所未有的方式重塑我们处理复杂问题的能力。作为一名长期关注量子算法与信息安全交叉领域的研究者,我亲眼见证了量子机器学习从理论构想走向实际应用的飞速发…...

【Sora 2视频后期处理黄金法则】:20年AI影像专家亲授5大不可绕过的帧级调优技巧

更多请点击: https://codechina.net 第一章:Sora 2视频后期处理的底层逻辑与帧级思维重构 Sora 2并非传统时间轴驱动的剪辑工具,其视频后期处理建立在扩散模型与隐空间帧序列联合优化的基础之上。每一帧不再作为孤立图像存在,而是…...

Burp Suite实操避坑指南:从抓包失败到漏洞验证的完整链路

1. 这不是又一本“Burp Suite入门指南”,而是一份我亲手调试过37次配置、在真实客户环境里跑通21个靶场、被5个刚转行的安全新人追着问细节的实操手记你点开这个标题,大概率正站在两个路口之间:一边是满屏英文弹窗、Proxy拦截失败、Repeater发…...

【2024新闻稿生产力白皮书】:实测17款Prompt后沉淀出的唯一高通过率模板(附A/B测试数据:发布成功率↑410%)

更多请点击: https://codechina.net 第一章:ChatGPT新闻稿写作模板的底层逻辑与范式演进 新闻稿生成并非简单拼接关键词,而是语义意图建模、事实锚定与传播修辞三重机制协同作用的结果。早期模板依赖规则引擎(如正则匹配预设句式…...

安卓高版本APP抓包失败原因与BurpSuite+雷电模拟器9实战绕过指南

1. 为什么高版本安卓APP抓包变得像拆弹——从Android 7到12的证书信任机制演进你有没有试过把BurpSuite的CA证书拖进雷电模拟器9里,双击安装,弹出“已安装但无法启用”的提示?或者App一启动就报“网络连接异常”,连登录页都打不开…...

Gemini模型迭代、推理成本、合规折旧、业务适配率——四大价值损耗源深度拆解,附可落地的季度健康度自检表

更多请点击: https://codechina.net 第一章:Gemini生命周期价值分析 Gemini 模型作为 Google 推出的多模态大语言模型系列,其生命周期价值不仅体现在推理性能与响应速度上,更贯穿于训练、部署、监控、迭代与退役全过程。理解这一…...

上位机知识篇---安装包文件名各部分的含义

torch-2.5.0a0872d972e41.nv24.08.17622132-cp310-cp310-linux_aarch64.whl这个长长的文件名是一个为特定平台预编译的 PyTorch 安装包(.whl 文件) 的名字。它遵循 Python 的 PEP 427 命名规范,每一部分都精确描述了该软件包的兼容性信息。我…...

Gemini SQL生成准确率暴跌87%?揭秘模型幻觉的4个致命诱因及实时校验方案

更多请点击: https://intelliparadigm.com 第一章:Gemini SQL生成准确率暴跌87%?揭秘模型幻觉的4个致命诱因及实时校验方案 近期多项基准测试显示,Gemini Pro 1.5 在复杂业务场景下的SQL生成任务中,准确率从历史平均9…...

深度学习篇---torch 和 torchvision

torch 和 torchvision 是 PyTorch 生态中最核心的两个库。简单来说,torch 是基础框架,负责张量计算和自动微分;而 torchvision 是专注于视觉任务的工具集,让你能方便地加载数据、使用预训练模型和进行图像处理。🔥 tor…...

【ChatGPT项目计划书生成实战指南】:20年PMO总监亲授5大高转化模板+3类避坑红线

更多请点击: https://kaifayun.com 第一章:ChatGPT项目计划书生成的核心价值与适用场景 在敏捷开发与跨职能协作日益普及的今天,项目计划书不再仅是交付物,更是对目标对齐、资源预判与风险共识的关键载体。ChatGPT驱动的项目计划…...

CentOS 7服务器上,从禁用Nouveau到成功点亮NVIDIA显卡的保姆级实录

CentOS 7服务器NVIDIA显卡驱动部署全指南:从Nouveau禁用到CUDA环境搭建当你第一次在CentOS 7服务器上部署NVIDIA显卡驱动时,那个看似简单的"禁用Nouveau"步骤往往会成为整个安装过程中最大的绊脚石。作为一位经历过无数次驱动安装的老手&#…...

Python 开发者如何通过 Taotoken 快速接入多款大模型 API

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Python 开发者如何通过 Taotoken 快速接入多款大模型 API 对于需要频繁实验不同大模型能力的 Python 开发者而言,管理多…...

为什么你的DeepSeek工具调用总是超时?揭秘底层Tool Executor线程池配置的2个致命默认值及修复代码

更多请点击: https://kaifayun.com 第一章:为什么你的DeepSeek工具调用总是超时?揭秘底层Tool Executor线程池配置的2个致命默认值及修复代码 DeepSeek-R1 模型在调用外部工具(如 HTTP API、数据库查询、Python 函数)…...

DeepSeek-R1模型压缩到<380MB还能保持98.7%对话准确率?——边缘设备量化微调四步法首次公开

更多请点击: https://intelliparadigm.com 第一章:DeepSeek边缘设备部署 DeepSeek系列大模型在边缘侧的轻量化部署,正成为工业质检、智能安防与车载语音等低延迟场景的关键技术路径。其核心挑战在于平衡模型精度、推理吞吐与硬件资源约束——…...

【AI问答/前端】前端满天过海局(一)

Axios感觉就像一堆ajax函数,再高深我就不懂了,Pinia可以当成是各组件之间的变量主动响应?这边改了,那边用到这个变量的也变了?跟vue插件传参不一样吧,感觉,vue还要写插槽传值(好像是这样,太久我忘了)。router这个路由我就蛋疼了,他上面的url是真变了呀,他是客户端…...

Kubernetes多集群管理策略:统一管理多个K8s集群

Kubernetes多集群管理策略:统一管理多个K8s集群 一、多集群管理概述 Kubernetes多集群管理是指在企业环境中管理多个独立的Kubernetes集群,实现统一的部署、监控和运维。 1.1 多集群场景 场景说明示例地域隔离不同区域部署独立集群北京、上海、广州各…...

Kubernetes自动化运维与CI/CD集成:构建高效的持续交付流水线

Kubernetes自动化运维与CI/CD集成:构建高效的持续交付流水线 一、CI/CD概述 CI/CD(持续集成/持续交付) 是一种自动化软件交付的方法论,在Kubernetes环境中集成CI/CD可以实现应用的自动化构建、测试和部署。 1.1 CI/CD流程 代码…...

Kubernetes安全加固指南:构建安全的容器平台

Kubernetes安全加固指南:构建安全的容器平台 一、Kubernetes安全概述 Kubernetes安全涉及多个层面,包括网络安全、Pod安全、数据安全、访问控制等。构建安全的Kubernetes集群需要从多个维度进行加固。 1.1 安全维度 维度说明关注点网络安全Pod间通信…...

初创公司如何借助Taotoken低成本启动AI产品开发

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 初创公司如何借助Taotoken低成本启动AI产品开发 对于初创公司而言,在资源有限的情况下启动AI产品开发,面临…...

Kubernetes可观测性体系构建:全面监控与故障排查指南

Kubernetes可观测性体系构建:全面监控与故障排查指南 一、可观测性概述 可观测性(Observability) 是指通过系统产生的数据来理解系统内部状态的能力。在Kubernetes中,可观测性体系包含三个核心维度:指标(…...

通过curl命令快速测试Taotoken的API连通性与返回

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过curl命令快速测试Taotoken的API连通性与返回 在集成大模型服务时,直接使用curl命令进行API测试是一种高效且通用的…...