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

数据结构与算法学习day21-回溯法

一、组合

1.题目

. - 力扣(LeetCode)

2思路

把组合问题抽象成树形结构(N叉树)

每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围

图中可以发现n相当于树的宽度,k相当于树的深度

回溯法的搜索过程就是一个树型结构的遍历过程,在如下图中,可以看出for循环用来横向遍历,递归的过程是纵向遍历。

那么如何在这个树上遍历,然后收集到我们要的结果集呢?

图中每次搜索到了叶子节点,我们就找到了一个结果

相当于只需要把达到叶子节点的结果收集起来,就可以求得 n个数中k个数的组合集合。

按照递归法写法去写回溯法即可。

1.递归函数的返回值以及参数

函数里一定有两个参数,既然是集合n里面取k个数,那么n和k是两个int型的参数。

然后还需要一个参数,为int型变量startIndex,这个参数用来记录本层递归的集合从哪里开始遍历,防止取到重复值。

2.回溯函数终止条件

path这个数组的大小如果达到k,说明我们找到了一个子集大小为k的组合了,在图中path存的就是根节点到叶子节点的路径。

3.单层搜索的过程

for循环每次从startIndex开始遍历,然后用path保存取到的节点i。

可以看出backtracking(递归函数)通过不断调用自己一直往深处遍历,总会遇到叶子节点,遇到了叶子节点就要返回。backtracking的下面部分就是回溯的操作了,撤销本次处理的结果。

总体代码:

class Solution {
private:vector<vector<int>> result; // 存放符合条件结果的集合vector<int> path; // 用来存放符合条件结果void backtracking(int n, int k, int startIndex) {if (path.size() == k) {result.push_back(path);return;}for (int i = startIndex; i <= n; i++) {path.push_back(i); // 处理节点backtracking(n, k, i + 1); // 递归path.pop_back(); // 回溯,撤销处理的节点}}
public:vector<vector<int>> combine(int n, int k) {backtracking(n, k, 1);return result;}
};

二、电话号码的字母组合

1.题目

17. 电话号码的字母组合 - 力扣(LeetCode)

2.思路

2.1 数字和字母如何映射

定义一个二维数组letterMap来映射。

同时需要把字符转换成数字

2.2 回溯法来解决n个for循环的问题

回溯三部曲:

1.传入参数

参数指定是有题目中给的string digits,然后还要有一个参数就是int型的index。这个index是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串),同时index也表示树的深度。

2.终止条件

当遍历到字符串最后一个字符时,把子集加入到结果中。

3.单层遍历逻辑

把字符转换为数字,同时映射出字符串。用for循环进行遍历目前字符串。需要注意的是,每次遍历字符串从0开始,因为这道题是多个字符串的组合题。上面那题属于单个数组的组合题。

总体代码:

class Solution {
private:const string letterMap[10] = {"", // 0"", // 1"abc", // 2"def", // 3"ghi", // 4"jkl", // 5"mno", // 6"pqrs", // 7"tuv", // 8"wxyz", // 9};public:vector<string> result;string s;//index为处理的位数void backtracking(const string& digits,int index){if(index == digits.size()){result.push_back(s);return;}//转换成数字int  digit = digits[index] - '0';string temp = letterMap[digit];for(int i = 0;i < temp.size();i++){s.push_back(temp[i]);backtracking(digits,index+1);s.pop_back();}}vector<string> letterCombinations(string digits) {if(digits.size() == 0) return result;backtracking(digits,0);return result;}
};

 三、组合总和

1.题目

39. 组合总和 - 力扣(LeetCode)

2.思路

本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。为了不重复,只能往后取数字。

2.1 传入参数

除了原来给的两个参数candidate和target,另外加了sum和index。sum用来计算取的值总和大小,index用来标记for循环的开始位置。因为这道题属于单集和求组合。

2.2 终止条件

如果sum大于target,则回溯。

如果sum等于target,则加入result。

2.3 单层循环逻辑

sum加上当前值,并把当前值加入到path子集,进行下一步的元素寻找。大于或者等于则返回,进行回溯,同时sum要把当前值减掉。

 

总体代码: 

class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int target,int sum,int index){if(sum > target) return;if(sum == target){result.push_back(path);return;}for(int i = index; i < candidates.size();i++){sum += candidates[i];path.push_back(candidates[i]);backtracking(candidates,target,sum,i);//递归path.pop_back();                      //回溯sum -= candidates[i];}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {backtracking(candidates,target,0,0);return result;}
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 好用的网页翻译插件
  • 01 Vim 编辑器的简单使用
  • 【CSS in Depth 2 精译_033】5.4 Grid 网格布局的显示网格与隐式网格(中)
  • uni-data-select 使用 localdata 传入数据出现 不回显 | 下拉显示错误的 解决方法
  • 什么是多模态大模型?
  • LNMP的简单安装(ubuntu)
  • 08 Shell Script条件判断
  • Vue3 Day1Day2-Vue3优势ref、reactive函数
  • vue 给循环列表的选中项加样式
  • 《仙境传说RO:新启航》游戏攻略,VMOS云手机辅助高效挂机助攻!
  • 【Elasticsearch系列十二】聚合-电视案例
  • 大数据新视界 --大数据大厂之探索ES:大数据时代的高效搜索引擎实战攻略
  • 【计算机网络】UDP 协议详解及其网络编程应用
  • Sqlmap中文使用手册 - File system access模块参数使用
  • 比特币10年价格数据(2014-2024)分析(进阶2_时间序列分析)
  • C++入门教程(10):for 语句
  • HTTP--网络协议分层,http历史(二)
  • js写一个简单的选项卡
  • miaov-React 最佳入门
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 基于游标的分页接口实现
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 提醒我喝水chrome插件开发指南
  • 微信开源mars源码分析1—上层samples分析
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 再次简单明了总结flex布局,一看就懂...
  • 仓管云——企业云erp功能有哪些?
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • 扩展资源服务器解决oauth2 性能瓶颈
  • # C++之functional库用法整理
  • # linux 中使用 visudo 命令,怎么保存退出?
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (C++17) std算法之执行策略 execution
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (算法)大数的进制转换
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .chm格式文件如何阅读
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .Net OpenCVSharp生成灰度图和二值图
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • @SuppressWarnings注解
  • @Transactional事务注解内含乾坤?
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [100天算法】-二叉树剪枝(day 48)
  • [20171102]视图v$session中process字段含义
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [AIGC] Java List接口详解
  • [Android]创建TabBar
  • [C#]C#学习笔记-CIL和动态程序集
  • [C#C++]类CLASS
  • [C/C++]数据结构 深入挖掘环形链表问题
  • [C]整形提升(转载)