经典算法之深度优先搜索(DFS)

news2025/2/23 14:58:07

在这里插入图片描述

  • 👑专栏内容:算法学习笔记
  • ⛪个人主页:子夜的星的主页
  • 💕座右铭:日拱一卒,功不唐捐。

目录

  • 一、前言
  • 二、基本概念
    • 1.简单介绍
    • 2. 官方概念
  • 三、动图分析
  • 四、模板框架
  • 五、例题分析
    • 组合问题
      • 题干描述:
      • 思路分析


一、前言

本文介绍了经典搜索算法: 深度优先搜索(DFS)

两个小故事:

岳云鹏的相声:孙越的爸爸带他参观家里面的聚宝盆,走到了一个密室门前,密室的门上上了一把锁,孙越的爸爸身上带了一万多把钥匙,他还忘了哪一把钥匙能打开个门了,于是就一把把试,试到了最后一把,门开了。

你叫DFS,在一次校园活动中你认识了三个非常漂亮的女孩,你想和她们进一步发展。于是,你选择了其中一个人,并对她展开了追求,你采用了 聊天->约会->表白 的恋爱三部曲。但是很不幸,她拒绝了你,于是你添加了第二个女生的微信,同样采取了你常用的三部曲。很不幸,第二个女生也拒绝你了。但是,你没有被困难打倒,于是你添加了第三个女生的微信,依旧是这三部曲,终于,第三个女生答应了你。你的朋友询问你,是如何找到女朋友的?,你答:我采用了DFS对象法🙈


二、基本概念

1.简单介绍

前言中的两个小故事,孙越的爸爸找钥匙开门的过程和DFS小朋友找女朋友都是一个搜索过程。
简而言之,搜索就是尝试问题中所有的可能性,在所有的可能性中找到正确的结果。而深度优先搜索用一句话概括就是:“ 一直往下走,走到最后还是走不通,那就换条路再走,直到无路可走。”用一个成语来形容,那就是 :“ 不撞南墙不回头。”
在这里插入图片描述

2. 官方概念

以下是维基百科上的解释:

深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。这个算法会尽可能深地搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。这种算法不会根据图的结构等信息调整执行策略

三、动图分析

DFS会从初始节点出发,按预定的顺序扩展到下一个节点,然后从下一节点出发继续扩展新的节点,不断递归执行这个过程,直到某个节点不能再扩展下一个节点为止。此时,则返回上一个节点重新寻找一个新的扩展节点。如此搜索下去,直到找到目标节点,或者搜索完所有节点为止。

动图:

在这里插入图片描述

四、模板框架

💞以下模板来自于大佬Carl:

void DFS(参数){
    if (终止条件){
        做要做的事
        return ;//退出 
    }
    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小))
    	{
    		处理节点;
            DFS(路径,选择列表);
            回溯:回到没用过
        }
    return ;//退出 
}

五、例题分析

组合问题

题干描述:

力扣77题:组合
给定两个整数 nk,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
输入:n = 4, k = 2
输出:

[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

输入:n = 1, k = 1
输出:

[[1]]

思路分析

图片来自于力扣
C语言代码:

int* path;
int pathTop;
int** ans;
int ansTop;

void DFS(int n, int k,int startIndex) {
    //当path中元素个数为k个时,我们需要将path数组放入ans二维数组中
    if(pathTop == k) {
        //path数组为我们动态申请,若直接将其地址放入二维数组,path数组中的值会随着我们回溯而逐渐变化
        //因此创建新的数组存储path中的值
        int* temp = (int*)malloc(sizeof(int) * k);
        int i;
        for(i = 0; i < k; i++) {
            temp[i] = path[i];
        }
        ans[ansTop++] = temp;
        return ;
    }

    int j;
    for(j = startIndex; j <=n ;j++) {
        //将当前结点放入path数组
        path[pathTop++] = j;
        //进行递归
        DFS(n, k, j + 1);
        //进行回溯,将数组最上层结点弹出
        pathTop--;
    }
}

int** combine(int n, int k, int* returnSize, int** returnColumnSizes){
    //path数组存储符合条件的结果
    path = (int*)malloc(sizeof(int) * k);
    //ans二维数组存储符合条件的结果数组的集合。(数组足够大,避免极端情况)
    ans = (int**)malloc(sizeof(int*) * 10000);
    pathTop = ansTop = 0;
    DFS(n, k, 1);
    //最后的返回大小为ans数组大小
    *returnSize = ansTop;
    //returnColumnSizes数组存储ans二维数组对应下标中一维数组的长度(都为k)
    *returnColumnSizes = (int*)malloc(sizeof(int) *(*returnSize));
    int i;
    for(i = 0; i < *returnSize; i++) {
        (*returnColumnSizes)[i] = k;
    }
    //返回ans二维数组
    return ans;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode146. LRU 缓存【python3哈希表+双向链表】利用OrderedDict以及自实现双向链表

题目&#xff1a; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。实现LRUCache类&#xff1a; LRUCache(int capacity) 以正整数作为容量capacity初始化 LRU 缓存int get(int key) 如果关键字key存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则…

【论文速递】9位院士Science88页长文:人工智能的进展、挑战与未来

【论文速递】9位院士Science88页长文&#xff1a;人工智能的进展、挑战与未来 【论文原文】&#xff1a;Intelligent Computing: The Latest Advances, Challenges and Future 获取地址&#xff1a;https://spj.science.org/doi/10.34133/icomputing.0006摘要&#xff1a; ​…

【阶段三】Python机器学习15篇:机器学习项目实战:支持向量机回归模型

本篇的思维导图: 项目实战(支持向量机回归模型) 项目背景 股票投资(Stock Investment)是指企业或个人用积累起来的货币购买股票,借以获得收益的行为。股票投资的收益是由“收入收益”和“资本利得”两部分构成的。收入收益是指股票投资者以股东身份,按照持股的份…

大网规划部署刷题讲解(带答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.大网规划刷题 前言 本章将会讲解大网规划刷题的讲解。 一.大网规划刷题 …

ArcGIS基础实验操作100例--实验85创建线要素间的最近垂线

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验85 创建线要素间的最近垂线 目录 一、实验背景 二、实验数据 三、实验步骤 &#xf…

【一文速通】数据分布不同解决办法

1. 构造合适的验证集当出现训练集和测试集分布不一致的&#xff0c;我们可以试图去构建跟测试集分布近似相同的验证集&#xff0c;保证线下验证跟线上测试分数不会抖动&#xff0c;这样我们就能得到稳定的benchmark。Qiuyan918在基于对抗验证的基础上&#xff0c;提出了三种构造…

为什么流媒体直播的延迟很高

通信技术的发展促进了视频点播和直播业务的兴起&#xff0c;4G 和 5G 网络技术的进步也使得流媒体技术变得越来越重要&#xff0c;但是网络技术并不能解决流媒体直播的高延迟问题&#xff0c;本文不会介绍网络对直播业务的影响&#xff0c;而是会分析直播中常见的现象 — 主播和…

Spring(1):拦截器

1 拦截器 拦截器是Spring中的概念&#xff0c;和过滤器类似&#xff0c;可以对用户请求进行拦截过滤处理。但是相对于过滤器而言&#xff0c;拦截器要的控制更加的细节&#xff0c;拦截器可以在三个地方进行执行&#xff1a; 可以在请求达到Controller控制器之前&#xff0c;…

VirtualBox 客户机/虚拟机无法时间同步?可能是你安装客户机插件的方式不对!

文章目录安装客户机插件的正确方式准备工作安装过程用户手册中的“客户机插件”安装客户机插件的正确方式 准备工作 所需包如下&#xff1a; GNU compiler (GCC)GNU Make (make)Kernel header fileslib* files 笔者亲测使用的 CentOS 7 Linux 内核版本为 3.10.0-1160.81.1.…

SQL索引概念(详解B+树)

SQL索引定义分类复合索引特性复合索引最左特性&#xff08;原则&#xff09;原理索引及其扫描类型索引的优缺点优点:缺点:索引工作原理BTree索引怎么判断是否创建索引&#xff1f;为什么Mysql用B树做索引而不用B-树或红黑树为什么索引快&#xff1f;定义 索引是一种排好序的快…

【数据结构】认清带头双向循环链表的庐山真面目

目录前言一、带头双向循环链表的介绍二、带头双向循环链表的类型重定义1.对数据类型进行重定义2.链表结点结构3.结点类型重定义三、常见函数操作的实现1.声明2.定义1. 申请新节点2. 初始化3. 销毁链表4. 打印链表5. 尾插数据6. 尾删数据7. 头插结点8.头删结点9. 在指定的位置前…

嵌入式开发的程序架构

前言 在嵌入式软件开发&#xff0c;包括单片机开发中&#xff0c;软件架构对于开发人员是一个必须认真考虑的问题。 软件架构对于系统整体的稳定性和可靠性是非常重要的&#xff0c;一个合适的软件架构不仅结构清晰&#xff0c;并且便于开发。 我相信在嵌入式或单片机软件开发…

聚焦云原生安全|安全狗亮相云原生产业联盟年会

1月9日&#xff0c;云原生产业联盟年会成功举办。 作为国内云原生安全领导厂商&#xff0c;安全狗也受邀参与此次大会。 安全狗高级副总裁陈荣有发表寄语 在此次线上会议中&#xff0c;安全狗凭借突出的云原生安全整体实力&#xff0c;通过层层筛选与审核&#xff0c;入选成为…

OpenCV从3D-2D 点对应中查找对象姿势solvePnP

1.概述&#xff1a;在使用相机拍照片时&#xff0c;大多数人会考虑拍的好不好看&#xff0c;关注相机中物体坐标的并不多&#xff0c;但是对于地信学科来说&#xff0c;如果能从照片中获取物体的真实位置&#xff0c;对地理信息获取大有帮助&#xff0c;在这里面&#xff0c;十…

深入分析Linux PCI驱动框架(三)

说明&#xff1a; Kernel版本&#xff1a;4.14ARM64处理器使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 先回顾一下PCIe的架构图&#xff1a; 本文将讲PCIe Host的驱动&#xff0c;对应为Root Complex部分&#xff0c;相当于PCI的Host Bridge部分&…

Vue 总结四 (ref, mixin, 插件, 插槽, VueX)

目录 ref 混入 mixin 插件 插槽 使用插槽的情景 使用方法 VueX 使用场景 使用 state 存放共享数据 actions 操作共享数据的API mutations 操作共享数据的API 生命周期图 ref 和id的区别 对于传统标签来说没有区别 都拿到的是 html内容 对于自定义的vue 的标签…

Spring事务源码分析

1. 前言 Spring支持两种事务管理的方式&#xff1a;声明式事务和编程式事务。编程式事务的优点是可以在代码里控制事务的粒度&#xff0c;实现细粒度的事务控制&#xff0c;缺点是对业务代码存在侵入性&#xff0c;代码复杂度较高&#xff0c;一般很少使用。声明式事务的优点是…

Linux下的动静态库

目录 认识动静态库 如何制作动静态库&#xff1f; 静态库 动态库 使用库 使用静态库 使用动态库 为什么动态链接是如此呢&#xff1f; 认识动静态库 我们在使用标准库的时候&#xff0c;需要有系统的头文件和系统的库文件&#xff0c;这个库文件是什么呢&#xff1f; …

Databend 借助对象存储帮你实现降本增效

本篇文章围绕着&#xff1a; 什么是对象存储当 Databend 遇到对象存储2022 年 Databend 利用对象存储降本的案例国内优秀的对象存储产品基于对象存储创业的产品 什么是对象存储 对象存储是一种可以非结构化存储和管理数据的技术。 可以简单理解为 NoSQL 接口方式存储和访问数…

linux系统中使用QT实现多媒体的功能方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用QT中的多媒体的功能。 目录 第一&#xff1a;多媒体基本简介 第二&#xff1a;应用实例实现 第三&#xff1a;程序运行效果 第一&#xff1a;多媒体基本简介 QT的多媒体模块提供了音频&#xff0c;视频&#xff…