LeetCode 热题 100 | 回溯(二)

目录

1  39. 组合总和

2  22. 括号生成

3  79. 单词搜索


菜鸟做题,语言是 C++,感冒快好版

关于对回溯算法的理解请参照我的上一篇博客;

在之后的博客中,我将只分析回溯算法中的 for 循环。

1  39. 组合总和

题眼:candidates 中的同一个数字可以无限制重复被选取。

根据题眼,for 循环结构如下:

for (int i = begin; i < candidates.size(); ++i) {output.push_back(candidates[i]);sum += candidates[i];helper(candidates, target, output, i, sum);sum -= candidates[i];output.pop_back();
}

与之前题解的唯一不同之处在于:递归时传的不再是 begin + 1,而是 i 。这是由于每个字母都可以被重复使用,因此我们可以从当前字母开始选择,而非跳过它。

思路说明图:

假设 target = 8 。在第一层函数中,i = begin = 0,即从 2 开始选择,再将 i 传给第二层函数;在第二层函数中,i = begin = 0,即从 2 开始选择,再将 i 传给第三层函数;以此类推。直到第五层函数,此时 sum = 2 + 2 + 2 + 2 > 8,即继续加下去也永远无法得到 target 。因此,返回到第四层函数,i += 1,即考虑 3 是否可行。以此类推。

由上述分析可得,递归终止条件为:

if (sum > target) return;
if (sum == target) {ans.push_back(output);return;
}

一是,当前 sum 已经大于 target,不能再增加下去了;二是,当前 sum 已经等于 target,也不能再增加下去了(区别在于,我们要将成功的组合记录下来)。

class Solution {
public:vector<vector<int>> ans;void helper(vector<int> & candidates, int target,vector<int> & output, int begin, int sum) {if (sum > target) return;if (sum == target) {ans.push_back(output);return;}for (int i = begin; i < candidates.size(); ++i) {output.push_back(candidates[i]);sum += candidates[i];helper(candidates, target, output, i, sum);sum -= candidates[i];output.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<int> output;helper(candidates, target, output, 0, 0);return ans;}
};

你可能会认为传递的参数太多,那你可以把它们都定义成全局变量。

2  22. 括号生成

for 循环结构如下:

output.push_back('(');
++l;
helper(output, n, l, r);
output.pop_back();
--l;
output.push_back(')');
++r;
helper(output, n, l, r);
output.pop_back();
--r;

这种写法和  78. 子集  很像。在  78. 子集  中,只有两种选择,即是否让当前字母进入子集;同样地,在本题中也只有两种选择,即当前坑位填左括号还是右括号(我们还设置了变量来记录当前左右括号的个数)。

递归终止条件为:

if (l > n || r > n || r > l) return;
if (l == n && r == n) {ans.push_back(output);return;
}

一是,如果当前左或右括号的个数大于所需的个数,则返回;二是,如果当前右括号的个数大于当前左括号的个数,则返回,这是因为该右括号肯定找不到配对的左括号;三是,如果左右括号的个数都等于所需的个数了,则记录成功的组合并返回。

class Solution {
public:vector<string> ans;void helper(string & output, int n, int l, int r) {if (l > n || r > n || r > l) return;if (l == n && r == n) {ans.push_back(output);return;}output.push_back('(');++l;helper(output, n, l, r);output.pop_back();--l;output.push_back(')');++r;helper(output, n, l, r);output.pop_back();--r;}vector<string> generateParenthesis(int n) {string output;helper(output, n, 0, 0);return ans;}
};

3  79. 单词搜索

非典型 for 循环结构如下:

visited[r][c] = 1;bool up = false, down = false, left = false, right = false;
if (r - 1 >= 0 && !visited[r - 1][c]) left = helper(board, word, r - 1, c, i + 1);
if (r + 1 < nr && !visited[r + 1][c]) right = helper(board, word, r + 1, c, i + 1);
if (c - 1 >= 0 && !visited[r][c - 1]) up = helper(board, word, r, c - 1, i + 1);
if (c + 1 < nc && !visited[r][c + 1]) down = helper(board, word, r, c + 1, i + 1);visited[r][c] = 0;return up || down || left || right;

这里的 “选择” 就是 “从当前位置出发,有四个方向可以走”。本来想写个 for 循环来遍历四个方向的,无奈这里有返回值,因此无法一概而论。这里的结构还是满足 “处理-递归-清除” 的格式,只是最后多了一个返回值。只要有一个方向能走得通,我们都返回 true 。

它不像之前的题一样,每个坑位/位置管好自己即可,而是要和后面的坑位/位置共荣辱。

递归终止条件:

if (board[r][c] != word[i]) return false;
if (i == word.size() - 1) return true;

一是,当前字母与 word 中的字母不同,返回 false;二是,已经找到了所有字母,返回 true 。

这道题感觉像是图论和回溯的杂合体啊啊啊。之前的题都是只有一个方向(右),而这道题有四个方向(上下左右)。

class Solution {
public:int nr, nc;vector<vector<int>> visited;bool helper(vector<vector<char>> & board, string word, int r, int c, int i) {if (board[r][c] != word[i]) return false;if (i == word.size() - 1) return true;visited[r][c] = 1;bool up = false, down = false, left = false, right = false;if (r - 1 >= 0 && !visited[r - 1][c])left = helper(board, word, r - 1, c, i + 1);if (r + 1 < nr && !visited[r + 1][c])right = helper(board, word, r + 1, c, i + 1);if (c - 1 >= 0 && !visited[r][c - 1])up = helper(board, word, r, c - 1, i + 1);if (c + 1 < nc && !visited[r][c + 1])down = helper(board, word, r, c + 1, i + 1);visited[r][c] = 0;return up || down || left || right;}bool exist(vector<vector<char>>& board, string word) {nr = board.size();nc = board[0].size();visited.resize(nr);for (auto & v : visited)v.resize(nc);for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (helper(board, word, i, j, 0)) return true;}}return false;}
};

说明:我们认为每个位置都有可能是 word 的起始点,因此使用双重 for 循环进行遍历。不过,只有当找完了 word 时才返回 true;反之,会走向最后的 false 。代码如下:

for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (helper(board, word, i, j, 0)) return true;}
}return false;

最好取 row 和 column 的首字母来定义变量,否则把自己都绕晕了。

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

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

相关文章

VBA_MF系列技术资料1-400

MF系列VBA技术资料1-400 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-0…

Java复习02 IO流

Java复习02 IO流 首先&#xff0c;“IO”在计算机里面代表的是“输入/输出”&#xff08;Input / Output&#xff09;&#xff0c;简单来说&#xff0c;就是计算机与外部世界进行数据交流的过程。比如&#xff0c;你在键盘上敲字&#xff0c;数据就输入到计算机里了&#xff0…

FastAPI 是什么?深入解析

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建基于 Python 的 API。它是一个开源项目&#xff0c;基于 Starlette 和 Pydantic 库构建而成&#xff0c;提供了强大的功能和高效的性能。 FastAPI 官网地址&#xff1a;fastapi.tiango…

Vue3自定义指令!!!

通过自定义指令实现菜单显示和权限控制问题。 一、新建一个在src目录下创建包directives&#xff0c;在包中创建一个ts文件。 import { useStore } from "/store/pinia";function hasRoles(role: any) {const pinaRoles useStore().roles;if (typeof role "s…

【RPG Maker MV 仿新仙剑 战斗场景UI (四)】

RPG Maker MV 仿新仙剑 战斗场景UI 四 三级战斗指令菜单效果代码完成效果 下篇预告 三级战斗指令菜单 仙剑1中三级战斗的菜单内容如下&#xff1a;使用、投掷、装备这三项。 效果 在RMMV中原始菜单中是没有这三级菜单的&#xff0c;因此需要重新进行添加进去。 代码 这里贴…

分布式思想

1、单体架构设计存在的问题 传统项目采用单体架构设计,虽然可以在一定的程度上解决企业问题,但是如果功能模块众多,并且将来需要二次开发.由于模块都是部署到同一台tomcat服务器中,如果其中某个模块代码出现了问题,将直接影响整个tomcat服务器运行. 这样的设计耦合性太高.不便…

19.ADC模数转换器知识点+AD单通道AD多通道应用程序示例

0. 江协科技/江科大-STM32标准库开发-各章节详细笔记-查阅传送门_江协科技stm32笔记-CSDN博客文章浏览阅读2.9k次&#xff0c;点赞44次&#xff0c;收藏128次。江协科技/江科大-STM32标准库开发-各章节详细笔记-传送门至各个章节笔记。基本上课程讲的每句都详细记录&#xff0c…

群晖 Synology Photos DSM7 自定义文件夹管理照片

背景 众所周知&#xff0c;目前群晖DSM7中使用Synology Photos做照片管理时&#xff0c;个人照片只能默认索引 /home/Photos 文件夹&#xff0c;但是如果个人照片很多或者用户很多时&#xff0c;共享文件夹/homes 所在的存储空间就会不够用 当然&#xff0c;如果你的存…

李彦宏“程序员将不再存在”言论被周鸿祎驳斥,网友怒怼:先把百度程序员都开除了

在 3 月 9 日央视的《对话》开年说节目上&#xff0c;百度创始人、董事长兼 CEO 李彦宏表示&#xff0c;基本上以后不会存在“程序员”这种职业了&#xff0c;因为只要会说话&#xff0c;人人都会具备程序员的能力。 “未来的编程语言只会剩下两种&#xff0c;一种叫做英文&am…

【刷题训练】LeetCode125. 验证回文串

验证回文串 题目要求 示例 1&#xff1a; 输入: s “A man, a plan, a canal: Panama” 输出&#xff1a;true 解释&#xff1a;“amanaplanacanalpanama” 是回文串。 示例 2&#xff1a; 输入&#xff1a;s “race a car” 输出&#xff1a;false 解释&#xff1a;“rac…

Java 设计模式系列:行为型-观察者模式

简介 观察者模式是一种行为型设计模式&#xff0c;又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都会得到通知并被自动更新。 观察者…

全面解析 Axios 请求库的基本使用方法

Axios 是一个流行的基于 Promise 的 HTTP 请求库&#xff0c;用于在浏览器和 Node.js 中进行 HTTP 请求。它提供了简单易用的 API&#xff0c;可以发送各种类型的请求&#xff08;如 GET、POST、PUT、DELETE等&#xff09;&#xff0c;并处理响应数据&#xff0c;Axios 在前端工…

朋友,代码库的“健身方案”要不要了解一下?

你有没有想过&#xff0c;你的代码库可能正面临“健康危机”—— 代码臃肿、低效交付、BUG隐藏、潜藏的安全风险…… “健身达人”上线 如果你的开发、安全和运维团队像是三位“健身达人”&#xff0c;那么极狐GitLab的DevSecOps线上成熟度评估&#xff0c;就是他们的“健身教…

09、用数据变量等控制 vue 项目标签中 CSS 样式的五种方法

通过 vue 中的变量值控制标签/组件样式 Ⅰ、通过 Vue3 的数据变量来控制 h1 标签样式&#xff1a;1、代码为&#xff1a;2、截图为&#xff1a; Ⅱ、通过 vue3 的 computed 来控制 h1 标签样式&#xff1a;1、代码为&#xff1a;2、截图为&#xff1a; Ⅲ、通过 vue3 的 comput…

MySQL gh-ost DDL 变更工具

文章目录 1. MDL 锁介绍2. 变更工具3. gh-ost 原理解析4. 安装部署5. 操作演示5.1. 重点参数介绍5.2. 执行变更5.3. 动态控制 6. 风险提示 1. MDL 锁介绍 MySQL 的锁可以分为四类&#xff1a;MDL 锁、表锁、行锁、GAP 锁&#xff0c;其中除了 MDL 锁是在 Server 层加的之外&am…

SpringBoot vue轮胎批发系统

SpringBoot vue轮胎批发系统 系统功能 首页 图片轮播 轮胎商品 评论 公告信息 搜索 购物车 立即购买 客服中心 登录注册 个人中心 我的订单 我的地址 我的收藏 后台管理 登录 个人中心 用户管理 轮胎分类管理 轮胎商品管理 公告信息管理 客服中心管理 轮播图管理 订单管理 …

Linux--基本知识入门

一.几个基本知识 终端: CtrlAltT 或者桌面/文件夹右键,打开终端切换为管理员: sudo su 退出:exit查看内核版本号: uname -a内核版本号含义: 5 代表主版本号;13代表次版本号;0代表修订版本号;30代表修订版本的第几次微调;数字越大表示内核越新. 二.目录…

FreeRTOS学习第10篇--队列使用示例

FreeRTOS学习第10篇–队列使用示例 本文目标&#xff1a;FreeRTOS学习第10篇–队列使用示例 按照本文的描述&#xff0c;可以进行简单的使用队列。 本文实验条件&#xff1a;拥有C语言基础&#xff0c;装有编译和集成的开发环境&#xff0c;比如&#xff1a;Keil uVision5 …

【Java 并发】AbstractQueuedSynchronizer

1 AQS 简介 在同步组件的实现中, AQS 是核心部分, 同步组件的实现者通过使用 AQS 提供的模板方法实现同步组件语义。 AQS 则实现了对同步状态的管理, 以及对阻塞线程进行排队, 等待通知等一些底层的实现处理。 AQS 的核心也包括了这些方面: 同步队列, 独占式锁的获取和释放, 共…

做一个微信小程序需要什么条件?

在移动互联网时代&#xff0c;微信小程序已成为连接用户与服务的重要桥梁。它们无需下载安装&#xff0c;使用方便&#xff0c;功能强大&#xff0c;成为商家和开发者的新宠。如果你想要开发一个微信小程序&#xff0c;需要满足哪些条件&#xff1f; 一、开发小程序的基本条件…