从零开始写算法——回溯篇3:括号生成 + 单词搜索

回溯算法(DFS)是算法面试中的重难点。很多同学觉得它难,是因为分不清什么时候该“恢复现场”,什么时候该“标记状态”。

今天我们通过两道经典的 LeetCode 题目——括号生成单词搜索,来对比分析回溯算法的两种不同模式:路径构造模式网格搜索模式

一、 路径构造模式:括号生成 (Generate Parentheses)

这道题是典型的“做选择”问题。你可以把它想象成手里拿着 n 个左括号和 n 个右括号,在 $2n$ 个空位上做填空题。

核心逻辑

我们在递归时需要时刻遵守两个规则,才能保证生成的括号是合法的:

  1. 手里还有存货才能放:只要左括号没用完 (left < n),就可以尝试放左括号。

  2. 不能欠债才能还:只有当前放下的左括号多于右括号时 (right < left),也就是有未闭合的左括号时,才能放右括号。

代码实现

这里使用了标准的push_backpop_back写法。这种写法的核心在于我们是在构造参数vals),每次递归前把东西放进去,递归回来后必须把它拿出来,恢复成原来的样子,以便进行下一次选择。

C++代码实现:

class Solution { // 手里拿着 n 个左括号和 n 个右括号,做填空题,时刻遵守两个规则 // 规则1 : left < n 规则2 : right < left vector<string> ans; void dfs(string& vals, int left, int right, int n) { // Base Case: 左右都用完了,说明构造完成 if (right == n) { ans.push_back(vals); return; } // 尝试放左括号 if (left < n) { vals.push_back('('); // 做选择 dfs(vals, left + 1, right, n); // 进入下一层 vals.pop_back(); // 撤销选择(恢复现场) } // 尝试放右括号 if (right < left) { vals.push_back(')'); // 做选择 dfs(vals, left, right + 1, n); // 进入下一层 vals.pop_back(); // 撤销选择(恢复现场) } } public: vector<string> generateParenthesis(int n) { string vals = ""; dfs(vals, 0, 0, n); return ans; } };

复杂度分析

  • 时间复杂度:O(4^n / sqrt(n))。

    • 这个复杂度与卡特兰数(Catalan Number)有关。简单理解,每个位置有两种选择,共有 2n 个位置,但因为有剪枝(规则限制),实际数量远小于 2^(2n)。

  • 空间复杂度:O(n)。

    • 主要消耗在递归调用栈和存储当前路径的vals字符串上,最大深度为 2n。


二、 网格搜索模式:单词搜索 (Word Search)

这道题属于“图/网格遍历”。与上一题不同,这里的“恢复现场”不是为了构造字符串,而是为了防止走回头路

核心逻辑

我们把每一个点作为起点,执行 DFS 搜索。

这里有一个非常关键的细节:什么时候标记节点?

  • 错误做法:在进入下一层递归前,标记下一个位置 (nx, ny)。这会导致起点无法被标记,以及逻辑判断复杂化。

  • 正确做法标记当前位置 (x, y)。也就是“进门后再锁门”。一旦进入 DFS 函数,先判断当前点是否匹配,匹配的话就标记为已访问(比如改为.),递归结束后再改回来。

代码实现

注意看代码中的注释,关于恢复现场和循环变量的处理是易错点。

C++代码实现:

class Solution { // 思路: 把每一个点作为起点然后对他执行dfs去遍历搜索是否存在这样的单词 // 每次上下左右找之前,把自己当前位置xy标记为. 注意是当前位置不是下一个位置 如果改的是nxny,那么下一步进去就无法通过borad[x][y] 和 word判断了 // 注意: 既然要恢复现场就要提前记录w,注意for里面不要用变量i会冲突 int dx[4] = {0, 1, 0, -1}; int dy[4] = {-1, 0, 1, 0}; bool ans; // i 代表当前匹配到了 word 的第几个字符 bool dfs(vector<vector<char>>& board, string word, int n, int i, int x, int y) { // 1. 判断当前格子字符是否匹配 if (word[i] != board[x][y]){ return false; } // 2. 匹配完成 if (i == n - 1) return true; // 3. 标记当前节点 (Backtracking 核心) // 提前记录便于恢复现场 char w = board[x][y]; // 避免重复使用到,标记为 '.' board[x][y] = '.'; // 4. 遍历四个方向 // 注意这里不能用 i 做为变量名(会与参数 i 冲突) for (int j = 0; j < 4; ++j) { int nx = x + dx[j]; int ny = y + dy[j]; // 越界检查及是否已访问检查 if (nx < 0 || nx >= board.size() || ny < 0 || ny >= board[0].size() || board[nx][ny] == '.') { continue; } // 只要有一条路走通了,就直接返回 true if (dfs(board, word, n, i + 1, nx, ny)) return true; } // 5. 恢复现场 board[x][y] = w; return false; } public: bool exist(vector<vector<char>>& board, string word) { int n = word.size(); for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[0].size(); ++j) { // 以每个格子为起点尝试 ans = dfs(board, word, n, 0, i, j); if (ans == true) return ans; } } return ans; } };

复杂度分析

  • 时间复杂度:O(M * N * 3^L)。

    • M 和 N 是网格的长宽,我们需要遍历每一个格子作为起点(M * N)。

    • L 是字符串word的长度。在 DFS 函数中,除了第一次有 4 个分支,之后因为不能走回头路,最多只有 3 个分支。所以是 3^L。

  • 空间复杂度:O(L)。

    • 空间消耗主要来自递归栈的深度,最大深度也就是单词的长度 L。


总结

通过这两道题,我们可以总结出 DFS 回溯的两个黄金法则:

  1. 构造类回溯(括号生成):目的是拼凑出一个结果。我们通过push_back添加元素进入下一层,出来后pop_back撤销。

  2. 搜索类回溯(单词搜索):目的是在图中寻找路径。我们通过修改board[x][y]为特殊字符来标记“当前正在访问”,递归结束后还原字符,以免影响其他路径的搜索。

记住:每一个 DFS 函数只负责管理自己脚下的节点(标记和恢复),不要试图去管理下一层节点的标记,否则容易出现逻辑死循环。

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

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

相关文章

2026年Q1值得关注的电动伸缩门生产厂家有哪些?

文章摘要 随着智能化浪潮席卷安防与出入口管理领域,电动伸缩门行业正迎来新一轮技术升级与市场洗牌。本文旨在为有采购需求的企事业单位提供一份客观的参考,综合考量品牌实力、技术特点、服务网络及市场口碑等多维度…

计算机毕业设计springboot新冠物资管理 SpringBoot疫情物资调配与追踪系统 SpringBoot突发公卫物资智慧管理平台

计算机毕业设计springboot新冠物资管理f2h4e &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。2020 年以来&#xff0c;突发公共卫生事件让口罩、防护服、检测试剂等物资成为一线“…

2026年阜阳沙发供货厂家综合评估:甄选3家实力厂商,赋能企业高效采购

文章摘要 随着消费者对家居品质与供应链效率要求的不断提升,选择一家可靠的沙发供货厂家成为酒店、公寓、房企及经销商降本增效的关键。本文基于供应链实力、产品工艺、定制能力、项目交付及服务保障五大核心维度,对…

【开题答辩过程】以《基于springboot的影迷推影社交平台》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看

个人简介慕婉学姐精通Java、PHP、微信小程序、Python、Golang和安卓开发等语言&#xff0c;擅长开发大数据、深度学习、网站、小程序、安卓应用和算法项目。平时从事项目定制开发、代码讲解、答辩教学和文档编写&#xff0c;也掌握一些降重技巧。感谢大家的持续关注&#xff01…

【快速EI检索 | EI稳定检索 | 征稿范围广 | Springer-Advances in Science, Tec】2026年人工智能与数字服务国际学术会议(ICADS 2026)

第二届人文地理与城乡规划国际学术会议&#xff08;HGURP 2026&#xff09; 2026 2nd International Conference on Human Geography and Urban-Rural Planning 2026年2月6日&#xff08;周五&#xff09;&#xff5c;线上召开 大会官网&#xff1a;www.hgurp.org 截稿时间…

自动化毕设 stm32的火灾监控与可视化系统(源码+硬件+论文)

文章目录 0 前言1 主要功能2 硬件设计(原理图)3 核心软件设计4 实现效果5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉…

【034】AQS 高频深度面试题(附接地气详解)- 必背 - 详解

【034】AQS 高频深度面试题(附接地气详解)- 必背 - 详解2026-01-21 01:36 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important…

LangChain多智能体系统详解:5种架构模式与实战案例实现

本文详细介绍了LangChain中的多智能体系统&#xff08;MAS&#xff09;&#xff0c;包括其定义、五种实现模式及其核心特性。通过构建搜索智能体的实际案例&#xff0c;展示了基于LangGraph的工作流和基于LangChain的双智能体架构两种实现方式。多智能体系统通过群体智能突破单…

从线程池到全局限流:并发失控的根因分析

一、问题不是“并发太大”&#xff0c;而是“没人对并发负责” 很多采集系统的并发失控&#xff0c;并不是因为工程师不知道要“控制并发”&#xff0c;而是因为并发从来没有被当成一种“平台级资源”来设计。 在早期阶段&#xff0c;我们构建采集任务时的并发逻辑往往很简单&a…

【快速EI检索 | 海外高校主办丨EI稳定检索 | 征稿范围广 】2026年生成式人工智能与教育国际学术会议(GAIE 2026)

2026年生成式人工智能与教育国际学术会议(GAIE 2026) 2026 International Conference on Generative Artificial Intelligence and Education (GAIE 2026) 2026年2月6日-2月8日 &#xff5c;新加坡 大会官网&#xff1a;www.icgaie.com 截稿时间&#xff1a;见官网&#xf…

网易企业邮箱珠海服务商:这5个关键优势你必须知道!

网易企业邮箱珠海服务商&#xff1a;这5个关键优势你必须知道&#xff01;在珠海这座充满活力的创新之城&#xff0c;企业数字化通信的稳定与安全是业务高效运转的基石。选择一家可靠的企业邮箱服务商&#xff0c;对于保障商务沟通、提升品牌形象至关重要。作为网易企业邮箱在珠…

【快速EI检索 | 高录用 | EI检索稳定 | 对学生友好会议 | JPCS出版有ISSN号,高录用,见刊快】2026年航空航天、智能感知与控制国际学术会议

2026年航空航天、智能感知与控制国际学术会议 2026 International Conference on Aerospace, Intelligent Perception and Control (AIPC 2026) 2026年2月6日-2月8日 &#xff5c;中国-昆明 大会官网&#xff1a;www.icaipc.org 截稿时间&#xff1a;见官网&#xff08;早投…

大厂Java岗面试复盘实录!

上个月班上的好好的突然被通知"毕业了"&#xff0c;现在工作也确实不好找。之前近一个月面了很多大大小小的公司降薪太严重都没考虑去&#xff0c;最后没办法本来都打算随便去一家了却偶然得到一个阿里的面试机会&#xff0c;足足面了七面&#xff08;我太难了&#…

SpringBoot+Vue 宠物领养系统管理平台源码【适合毕设/课设/学习】Java+MySQL

摘要 随着社会经济的快速发展和人们生活水平的不断提高&#xff0c;宠物已成为许多家庭的重要成员。然而&#xff0c;流浪动物问题日益突出&#xff0c;传统线下领养方式存在信息不对称、流程繁琐等问题。为解决这一问题&#xff0c;基于互联网的宠物领养平台应运而生&#xff…

打破协议壁垒:疆鸿智能DEVICENET与EtherCAT在新能源产线中的毫秒级协同

打破协议壁垒&#xff1a;疆鸿智能DEVICENET与EtherCAT在新能源产线中的毫秒级协同一、网关在工业互联中的作用 在工业自动化系统中&#xff0c;网关承担着协议转换、数据交互与网络集成的核心职能。尤其在多品牌设备共存的场景下&#xff0c;网关通过协议兼容与数据映射&…

吃透这 5 个 C/C++ 就业方向,应届生也能拿高薪 Offer

如果你现在正为 C 开发方向感到迷茫&#xff0c;不知道该往哪走&#xff0c;那这篇内容或许能给你一些思路。 相信我&#xff0c;几年后再回头看&#xff0c;你一定会感激此刻为方向努力探索的自己。 C 作为当下依然主流的面向对象语言&#xff0c;应用场景非常广泛 —— 总有…

高并发经验:所有Java程序员必备!

现在互联网企业招聘对于“高并发”这块的考察可以说是越来越注重了。基本上你简历上有高并发相关经验&#xff0c;就能成为企业优先考虑的候选人。其原因在于&#xff0c;企业真正需要的是能独立解决问题的人才。每年面试找工作的人很多&#xff0c;技术水平也是高低不一&#…

华强北商城二手手机管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着二手手机市场的快速发展&#xff0c;华强北作为中国最大的电子产品集散地之一&#xff0c;其二手手机交易规模逐年扩大。然而&#xff0c;当前市场上缺乏高效、系统的管理工具&#xff0c;导致交易过程中信息不透明、管理混乱等问题频发。传统的手工记录或简单的电子表…

IT就业寒冬,程序员还有必要死磕技术吗?

今年的程序员可以说是最焦虑的一个群体了&#xff0c;面试找工作投简历没人理&#xff0c;有面试机会也面试不过&#xff0c;面试进去还干不长...于是&#xff0c;程序员们纷纷直呼&#xff1a;互联网寒冬又双叒叕来了&#xff0c;环境不好努力也没用躺平算了。真的是这样吗&am…

【2025最新】基于SpringBoot+Vue的mvc高校办公室行政事务管理系统管理系统源码+MyBatis+MySQL

摘要 随着高校行政管理事务的日益复杂化和信息化需求的不断提升&#xff0c;传统的手工管理模式已难以满足高效、精准的管理需求。高校办公室行政事务管理系统旨在通过信息化手段优化行政流程&#xff0c;提升管理效率&#xff0c;减少人为错误。该系统通过整合人事、财务、设备…