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

数据结构(六)—— 二叉树(4)回溯

文章目录

  • 一、题
  • 1 257 二叉树的所有路径
    • 1.1 写法1
    • 1.2 写法2


一、题

1 257 二叉树的所有路径

1.1 写法1

递归+回溯:回溯是递归的副产品,只要有递归就会有回溯

首先考虑深度优先搜索;而题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。
在这里插入图片描述
递归和回溯就是一家的,本题也需要回溯。

1、确定递归函数输入输出
要传入根节点,记录每一条路径的vector<int>&,和存放结果集的vector<string>&,这里递归不需要返回值,
void traversal(TreeNode* cur, vector<int>& path, vector<string>& result)
2、确定递归终止条件
一般来说都是if(cur == NULL) return,但是本题要找到叶子节点,就开始结束的处理逻辑了(把路径放进result里)。
那么什么时候算是找到了叶子节点? 是当 cur不为空,其左右孩子都为空的时候,就找到叶子节点。

if (cur->left == NULL && cur->right == NULL) { // 遇到叶子节点string sPath;for (int i = 0; i < path.size() - 1; i++) { // 将path里记录的路径转为string格式sPath += to_string(path[i]);sPath += "->";}sPath += to_string(path[path.size() - 1]); // 记录最后一个节点(叶子节点)result.push_back(sPath); // 收集一个路径return;
}

3、确定单层递归逻辑
因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路径上的节点,先放进path中。
path.push_back(cur->val);

然后是递归和回溯的过程,上面说过没有判断cur是否为空,那么在这里递归的时候,如果为空就不进行下一层递归了。
所以递归前要加上判断语句,下面要递归的节点是否为空,如下
if (cur->left) traversal(cur->left, path, result);
此时还没完,递归完,要做回溯啊,因为path 不能一直加入节点,它还要删节点,然后才能加入新的节点。

if (cur->left) {traversal(cur->left, path, result);path.pop_back(); // 回溯
}
if (cur->right) {traversal(cur->right, path, result);path.pop_back(); // 回溯
}

4、整合traversal()

class Solution {
private:void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {path.push_back(cur->val); // 中,中为什么写在这里,因为最后一个节点也要加入到path中 // 这才到了叶子节点if (cur->left == NULL && cur->right == NULL) {string sPath;for (int i = 0; i < path.size() - 1; i++) {sPath += to_string(path[i]);sPath += "->";}sPath += to_string(path[path.size() - 1]);result.push_back(sPath);return;}if (cur->left) { // 左 traversal(cur->left, path, result);path.pop_back(); // 回溯}if (cur->right) { // 右traversal(cur->right, path, result);path.pop_back(); // 回溯}}public:vector<string> binaryTreePaths(TreeNode* root) {vector<string> result;vector<int> path;if (root == NULL) return result;traversal(root, path, result);return result;}
};

1.2 写法2

1、确定输入输出
输入:节点、每条路径string、每条路径组成的vector<string>&
输出:空
void traversal(TreeNode* cur, string path, vector<string>& result)

注意:函数输出定义的是string,每次都是复制赋值,没使用引用,否则就无法做到回溯的效果。(这里涉及到C++语法知识)
2、确定退出条件

if (cur->left == NULL && cur->right == NULL) {result.push_back(path);return;
}

3、确定单层逻辑
中左右

path += to_string(cur->val); // 中
...  // 退出条件
if (cur->left) traversal(cur->left, path + "->", result); // 左
if (cur->right) traversal(cur->right, path + "->", result); // 右

4、整合

class Solution {
private:void traversal(TreeNode* cur, string path, vector<string>& result) {path += to_string(cur->val); // 中if (cur->left == NULL && cur->right == NULL) {result.push_back(path);return;}if (cur->left) traversal(cur->left, path + "->", result); // 左if (cur->right) traversal(cur->right, path + "->", result); // 右}public:vector<string> binaryTreePaths(TreeNode* root) {vector<string> result;string path;if (root == NULL) return result;traversal(root, path, result);return result;}
};

在哪儿回溯的?
如上代码貌似没有看到回溯的逻辑,其实不然,回溯就隐藏在traversal(cur->left, path + "->", result);中的 path + "->"。 每次函数调用完,path并没有加上"->",这就是回溯了。

使用如下代码可以更好的体会到回溯

if (cur->left) {path += "->";traversal(cur->left, path, result); // 左path.pop_back(); // 回溯 '>'path.pop_back(); // 回溯 '-'
}
if (cur->right) {path += "->";traversal(cur->right, path, result); // 右path.pop_back(); // 回溯 '>' path.pop_back(); //  回溯 '-' 
}
http://www.lryc.cn/news/65218.html

相关文章:

  • JVM基础知识(一)
  • ASP.NET Core Web API用户身份验证
  • 785. 快速排序
  • C6678学习-IPC
  • 利用 Delte-Sigma ADC简化电路设计
  • 如何在 Windows 11 启用 Hyper-V
  • 哈希表企业应用-DNA的字符串检测
  • Kafka运维与监控
  • 【Redis—哨兵机制】
  • MySQL学习笔记第七天
  • 中级软件设计师备考---程序设计语言和法律法规知识
  • Leetcode434. 字符串中的单词数
  • C++ cmake工程引入qt6和Quick 教程
  • JavaEE - 网络编程
  • 【Android车载系列】第11章 系统服务-SystemServer自定义服务
  • Lerna
  • 迁移学习 pytorch
  • 【python】keras包:深度学习( RNN循环神经网络 Recurrent Neural Networks)
  • vue框架快速入门
  • Java连接顺丰开放平台
  • 前端三剑客 - HTML
  • 【计算机视觉 | 自然语言处理】BLIP:统一视觉—语言理解和生成任务(论文讲解)
  • c++基础-运算符
  • 美术馆c++
  • 浅谈MySQL索引以及执行计划
  • 在c++项目中使用rapidjson(有具体的步骤,十分详细) windows10系统
  • 编译方式汇总:Makefile\configure\autogen.sh\configure.ac、Makefile.am文件
  • explicit关键字
  • [优雅的面试] 你了解python的对象吗
  • 【hello Linux】线程概念