DFS(深度优先搜索)与回溯算法详解
DFS(深度优先搜索)与回溯算法详解
一、DFS 基础
1. 什么是DFS?
深度优先搜索(Depth-First Search,DFS)是一种用于遍历或搜索树或图的算法。其核心思想是:
- 一条路走到黑:从起点出发,尽可能深入未访问的分支,直到无法继续前进。
- 回溯:当走到尽头时,回退到上一个分叉点,选择另一条未探索的路径继续深入。
2. DFS 的实现方式
DFS 可以通过两种方式实现:
- 递归:利用函数调用栈隐式实现回溯。
- 显式栈:手动维护一个栈来模拟递归过程。
示例:二叉树的DFS遍历
struct TreeNode {int val;TreeNode* left;TreeNode* right;
};// 递归实现DFS(前序遍历)
void dfs(TreeNode* root) {if (!root) return;cout << root->val << " "; // 访问当前节点dfs(root->left); // 递归左子树dfs(root->right); // 递归右子树
}
二、回溯算法
1. 什么是回溯?
回溯(Backtracking)是一种通过“试错”寻找问题解的算法。它在DFS的基础上,通过剪枝(Pruning)避免无效搜索,通常用于解决组合、排列、子集等需要穷举所有可能性的问题。
2. 回溯的核心步骤
- 选择:在当前状态下,做出一个可能的决策。
- 递归:基于这个决策,进入下一层递归。
- 撤销:递归返回后,撤销当前决策,回到之前的状态(即“回溯”)。
3. 回溯模板
void backtrack(路径, 选择列表) {if (满足终止条件) {将路径加入结果集;return;}for (选择 : 选择列表) {if (选择不合法) continue; // 剪枝做出选择; // 将选择加入路径backtrack(新路径, 新选择列表);撤销选择; // 将选择从路径中移除(回溯)}
}
三、经典问题与代码实现
1. 全排列问题
问题描述:给定无重复元素的数组 [1,2,3]
,返回所有可能的排列。
示例代码:
vector<vector<int>> permute(vector<int>& nums) {vector<vector<int>> res;vector<int> path;vector<bool> used(nums.size(), false); // 记录元素是否被使用function<void()> backtrack = [&]() {if (path.size() == nums.size()) {res.push_back(path);return;}for (int i = 0; i < nums.size(); i++) {if (used[i]) continue; // 剪枝:已使用的元素跳过used[i] = true; // 做出选择path.push_back(nums[i]);backtrack();path.pop_back(); // 撤销选择used[i] = false;}};backtrack();return res;
}
2. 组合总和问题
问题描述:给定候选数组 [2,3,6,7]
和目标值 7
,找出所有和为 7
的组合(元素可重复使用)。
示例代码:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<vector<int>> res;vector<int> path;sort(candidates.begin(), candidates.end()); // 排序便于剪枝function<void(int, int)> backtrack = [&](int start, int sum) {if (sum == target) {res.push_back(path);return;}for (int i = start; i < candidates.size(); i++) {if (sum + candidates[i] > target) break; // 剪枝:超过目标值跳过path.push_back(candidates[i]);backtrack(i, sum + candidates[i]); // 允许重复使用元素(i不+1)path.pop_back();}};backtrack(0, 0);return res;
}
3. N皇后问题
问题描述:在 N×N 的棋盘上放置 N 个皇后,使得它们不能互相攻击。
示例代码:
vector<vector<string>> solveNQueens(int n) {vector<vector<string>> res;vector<string> board(n, string(n, '.')); // 初始化棋盘function<bool(int, int)> isValid = [&](int row, int col) {// 检查列是否有冲突for (int i = 0; i < row; i++) {if (board[i][col] == 'Q') return false;}// 检查左上对角线for (int i = row-1, j = col-1; i >=0 && j >=0; i--, j--) {if (board[i][j] == 'Q') return false;}// 检查右上对角线for (int i = row-1, j = col+1; i >=0 && j < n; i--, j++) {if (board[i][j] == 'Q') return false;}return true;};function<void(int)> backtrack = [&](int row) {if (row == n) {res.push_back(board);return;}for (int col = 0; col < n; col++) {if (!isValid(row, col)) continue; // 剪枝:非法位置跳过board[row][col] = 'Q'; // 放置皇后backtrack(row + 1); // 处理下一行board[row][col] = '.'; // 回溯}};backtrack(0);return res;
}
四、回溯算法的优化技巧
-
剪枝:提前终止不可能得到解的路径。
- 条件剪枝:如组合总和问题中的
sum + candidates[i] > target
。 - 去重剪枝:如全排列问题中跳过已使用的元素。
- 条件剪枝:如组合总和问题中的
-
排序预处理:对输入数组排序,便于剪枝(如组合总和问题)。
-
记忆化:记录已访问的状态,避免重复计算(如数独问题)。
五、DFS与回溯的关系
- DFS 是回溯的实现方式:回溯算法通常通过递归的DFS实现。
- 回溯是DFS的应用场景:DFS用于遍历所有可能性,回溯通过剪枝优化DFS的效率。
- 区别:
- DFS 更强调遍历所有路径(如二叉树的遍历)。
- 回溯 更强调通过试错寻找解(如组合、排列问题)。
六、总结
- DFS 是遍历树或图的算法,核心是“一条路走到黑”。
- 回溯 是基于DFS的优化策略,通过“试错+剪枝”寻找问题的解。
- 关键步骤:选择 → 递归 → 撤销选择(回溯)。
- 经典问题:全排列、组合总和、N皇后、子集、数独等。
练习题
- 实现子集问题(返回数组的所有子集)。
- 解决数独问题(填充所有空格)。
- 优化全排列代码,处理输入数组包含重复元素的情况。
相关文章:
DFS(深度优先搜索)与回溯算法详解
DFS(深度优先搜索)与回溯算法详解 一、DFS 基础 1. 什么是DFS? 深度优先搜索(Depth-First Search,DFS)是一种用于遍历或搜索树或图的算法。其核心思想是: 一条路走到黑:从起点出发…...

服务器虚拟化技术详解与实战:架构、部署与优化
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 引言 在现代 IT 基础架构中,服务器虚拟化已成为提高资源利用率、降低运维成本、提升系统灵活性的重要手段。通过服务…...

数据分析系列--②RapidMiner导入数据和存储过程
一、下载数据 二、导入数据 1. 在本地计算机中创建3个文件夹 2. 从本地选择.csv或.xlsx 三、界面说明 四、存储过程 1.保存 Congratulations, you are done. 一、下载数据 点击下载AssociationAnalysisData.xlsx数据集 二、导入数据 1. 在本地计算机中创建3个文件夹 2. 从…...

CSS 背景与边框:从基础到高级应用
CSS 背景与边框:从基础到高级应用 1. CSS 背景样式1.1 背景颜色示例代码:设置背景颜色 1.2 背景图像示例代码:设置背景图像 1.3 控制背景平铺行为示例代码:控制背景平铺 1.4 调整背景图像大小示例代码:调整背景图像大小…...

国内外人工智能AI工具网站大全(一键收藏,应有尽有)
本文由 大侠(AhcaoZhu)原创,转载请声明。 链接: https://blog.csdn.net/Ahcao2008 国内外人工智能AI工具网站大全(一键收藏,应有尽有) 摘要一、AI写作工具二、AI图像工具2.1、常用AI图像工具2.2、AI图片插画生成2.3、AI图片背景移…...
Java中初步使用websocket(springBoot版本)
一、什么是websocket WebSocket是一种在Web应用程序中实现实时双向通信的协议。它为浏览器和服务器之间提供了一种持久连接,在一个连接上可以双向传输数据。相比传统的HTTP协议,WebSocket具有更低的延迟和更高的效率。 WebSocket使用了类似于握手的方式来…...

2025年大年初一篇,C#调用GPU并行计算推荐
C#调用GPU库的主要目的是利用GPU的并行计算能力,加速计算密集型任务,提高程序性能,支持大规模数据处理,优化资源利用,满足特定应用场景的需求,并提升用户体验。在需要处理大量并行数据或进行复杂计算的场景…...

K8S ReplicaSet 控制器
一、理论介绍 今天我们来实验 ReplicaSet 控制器(也叫工作负载)。官网描述如下: 1、是什么? ReplicaSet 副本集, 维护一组稳定的副本 Pod 集合。 2、为什么需要? 解决 pod 被删除了,不能自我恢…...

FreeRTOS学习 --- 任务调度
开启任务调度器 作用:用于启动任务调度器,任务调度器启动后, FreeRTOS 便会开始进行任务调度 该函数内部实现,如下: 1、创建空闲任务(优先级最低) 2、如果使能软件定时器,则创建定…...

【小鱼闪闪】单片机开发工具——米思齐软件下载安装(图文)
浏览器打开网址 mixly.org, 在软件平台选择mixly离线版。 最新版本为3.0,会支持audinio, ESP32、ESP8266 , 可以选择下载安装器或者完整版。 这里选择下载安装器,下载后运行“一键更新.bat”,即可自动下载最新版本的M…...

MFC开发,给对话框添加垂直滚动条并解决鼠标滚动响应的问题
无论在使用QT或者MFC进行界面开发时,都会出现在一个对话框里面存在好多的选项,导致对话框变得非常长或者非常大,就会显现的不美观,在这种情况下通常是添加一个页面的滚动条来解决这个问题,下面我们就来介绍给MFC的对话…...
动态规划DP 最长上升子序列模型 导弹防御模型(题目分析+C++完整代码实现)
概览检索 动态规划DP 最长上升子序列模型 导弹防御系统 原题链接 AcWiing 187. 导弹防御系统 题目描述 为了对抗附近恶意国家的威胁,R国更新了他们的导弹防御系统。 一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。 例如࿰…...

LevelDB 源码阅读:写入键值的工程实现和优化细节
读、写键值是 KV 数据库中最重要的两个操作,LevelDB 中提供了一个 Put 接口,用于写入键值对。使用方法很简单: leveldb::Status status leveldb::DB::Open(options, "./db", &db); status db->Put(leveldb::WriteOptions…...
药店药品销售管理系统的设计与实现
标题:药店药品销售管理系统的设计与实现 内容:1.摘要 摘要:本文介绍了药店药品销售管理系统的设计与实现。该系统旨在提高药店的运营效率和管理水平,通过信息化手段实现药品销售、库存管理、财务管理等功能。本文详细阐述了系统的需求分析、设计思路、技…...
人格分裂(交互问答)-小白想懂Elasticsearch
通过交互式追问了解一个中间件 ? 啥是Elasticsearch ! 分布式搜索和分析引擎 ? 为啥是分布式搜索,单体难道用不了吗 ? 实际上是说这个东西可以分布式部署 ! 单机可用但扩展性差,分布式通过分片、副本和负载均衡实现海量数据存储与高并发处理 ? 提…...
【论文投稿-第八届智能制造与自动化学术会议(IMA 2025)】HTML, CSS, JavaScript:三者的联系与区别
大会官网:www.icamima.org 目录 前言 一、HTML(超文本标记语言):网页的骨架 HTML 的作用: 例子: 总结: 二、CSS(层叠样式表):网页的外观设计 CSS 的…...
python | OpenCV小记(一):cv2.imread(f) 读取图像操作(待更新)
python | OpenCV小记(一):cv2.imread(f)读取图像操作 1. 为什么 [:, :, 0] 提取的是第一个通道(B 通道)?OpenCV 的通道存储格式索引操作 [:, :, 0] 的解释常见误解 1. 为什么 [:, :,…...

网络工程师 (9)文件管理
一、树形目录结构 (一)定义与构成 树形目录结构由一个根目录和若干层子文件夹(或称为子目录)组成,它像一棵倒置的树。这棵树的根称为根文件夹(也叫根目录),从根向下,每一…...
Java中的线程池参数(详解)
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {} 此构造方法的参数如下: int corePoolSize&…...

2 MapReduce
2 MapReduce 1. MapReduce 介绍1.1 MapReduce 设计构思 2. MapReduce 编程规范3. Mapper以及Reducer抽象类介绍1.Mapper抽象类的基本介绍2.Reducer抽象类基本介绍 4. WordCount示例编写5. MapReduce程序运行模式6. MapReduce的运行机制详解6.1 MapTask 工作机制6.2 ReduceTask …...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...