代码随想录 | Day21 | 二叉树:找树左下角的值路径总和

embedded/2024/9/23 21:24:23/

代码随想录 | Day21 | 二叉树:找树左下角的值&&路径总和

主要学习内容:

1.利用二叉树的谦虚遍历进行题目解答

2.to_string函数的使用

513.找树左下角的值

513. 找树左下角的值 - 力扣(LeetCode)

解法一:回溯

思路:

难突破的点是我们怎么知道我们找的叶子结点是最左边的

其实只需要一直往下遍历,每一层最先遍历到的肯定是左边的

那如何知道是最下面的呢?

深度最深才能是最下面的

所以我们的目标就是找深度最深的叶子结点,保存第一个遍历到的深度最深的结点。这就是我们的答案

1.函数参数和返回值

int res;
int curdepth=0;
void tra(TreeNode *t,int depth)

res记录结果

curdepth用于更新当前的最大深度

depth为当前结点的深度

2.终止条件

if(t->left==nullptr&&t->right==nullptr)
{if(depth>curdepth){res=t->val;curdepth=depth;}return;
}

遍历到叶子结点并且当前叶子结点深度最深,就是我们要的答案,保存后再更新一下当前最大深度,用于找更下层的结点

3.本层代码逻辑

if(t->left)tra(t->left,depth+1);
if(t->right)tra(t->right,depth+1);

在上面更新完结果后,继续遍历左右子树,+1是每层遍历深度+1

//不省略回溯的版本
if(t->left)
{depth++;tra(t->left,depth);depth--;
}
if(t->right)
{depth++;tra(t->right,depth);depth--;
}

4.完整代码

class Solution {
public:vector<string> res;void tra(string s,TreeNode *t){if(t==nullptr)return;if(t->left==nullptr&&t->right==nullptr){s+=to_string(t->val);res.push_back(s);return;}s+=to_string(t->val);s+="->";tra(s,t->left);tra(s,t->right);}vector<string> binaryTreePaths(TreeNode* root) {string s;tra(s,root);return res;}
};

解法二:层序遍历

我们每层第一个元素就是最左边的元素,每次都更新一下,到最后一层也会更新

只需要在模板的基础上再把每层第一个元素更新一下就行(不清楚模板可以翻看前面的层序遍历相关)

class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode *> q;q.push(root);int res;while(!q.empty()){int size=q.size();res=q.front()->val;//更新for(int i=0;i<size;i++){TreeNode *t=q.front();q.pop();if(t->left)q.push(t->left);if(t->right)q.push(t->right);}}return res;}};

112.路径总和

112. 路径总和 - 力扣(LeetCode)

解法:回溯

一个经典的树的路径问题,可以刷完回溯算法后再回来看

1.函数参数和返回值

bool flag=false;
void tra(TreeNode *t,int target)

flag是标记是否成功,找到就为ture

target是用来减的,减到0就说明找到了答案,利用一个反向思维吧算是

2.终止条件

if(t->left==nullptr&&t->right==nullptr)
{if(target==0)flag=true;
}

是叶子结点且已经减到了0,那么就是答案,标记为true

3.本层代码逻辑

易错

减去的是t的子树的val而不是t本身的val

调用的时候就要减去,这样方便终止条件进行比较,不然进入本层调用函数以后还要现场加或者减容易搞混

if(t->left)tra(t->left,target-t->left->val);
if(t->right)tra(t->right,target-t->right->val);

完整代码:

class Solution {
public:bool flag=false;void tra(TreeNode *t,int target){if(t->left==nullptr&&t->right==nullptr){if(target==0)flag=true;}if(t->left)tra(t->left,target-t->left->val);if(t->right)tra(t->right,target-t->right->val);}bool hasPathSum(TreeNode* root, int targetSum) {if(root==nullptr)return false;tra(root,targetSum-root->val);return flag;}
};

http://www.ppmy.cn/embedded/110938.html

相关文章

ThreeJS入门(001):简介、下载安装、历史、应用场景、竞品

查看本专栏目录 - 本文是第 001篇入门文章 文章目录 一、 Three.js 简介二、 Three.js 的历史与发展三、 公司背景四、下载安装五、官方网站六、应用范围场景七、相关竞品 一、 Three.js 简介 Three.js 是一个基于 WebGL 的 JavaScript 3D 库&#xff0c;它使得在 Web 上创建和…

Python中的私有属性与方法:解锁面向对象编程的秘密

在Python的广阔世界里&#xff0c;面向对象编程&#xff08;OOP&#xff09;是一种强大而灵活的方法论&#xff0c;它帮助我们更好地组织代码、管理状态&#xff0c;并构建可复用的软件组件。而在这个框架内&#xff0c;私有属性与方法则是实现封装的关键机制之一。它们不仅有助…

51单片机+proteus+学习3(串口、矩阵按键)

1.串口 1.1基本概念 1.1.1串口的简介 STC89C52有两个引脚是专门用来做UART(通用异步收发传输器)串行通信的&#xff0c;一个是P3.0,另一个是P3.1,它们还分别有另外的名字叫作RXD和TXD,由它们组成的通信接口就叫作串行接口&#xff0c;简称串口。 &#xff08;1&#xff09;G…

深入理解java并发编程之aqs框架

跟synchronized 相比较&#xff0c;可重入锁ReentrankLock其实原理有什么不同&#xff1f; 所得基本原理是为了达到一个目的&#xff1b;就是让所有线程都能看到某种标记。synchronized通过在对象头中设置标记实现了这一目的&#xff0c;是一种JVM原生的锁实现方式。而Reentran…

前端封装组件可视化库

在 Vue 项目中&#xff0c;如果你希望封装的组件库能够可视化并调整默认参数&#xff0c;你可以考虑使用以下工具和库&#xff1a; Storybook: Storybook 是一个非常流行的工具&#xff0c;用于构建和展示 UI 组件。它允许你以独立的方式开发组件&#xff0c;并能够直观地调整组…

Python中的列表、元组与字典有什么区别

文章目录 引言第一部分&#xff1a;列表&#xff08;List&#xff09;第二部分&#xff1a;元组&#xff08;Tuple&#xff09;第三部分&#xff1a;字典&#xff08;Dictionary&#xff09;对比分析附录 引言 Python作为一种高级编程语言&#xff0c;以其简洁易读的语法和强大…

centos上开启mysql远程访问功能

自从mysql8以后&#xff0c;mysql有些命令变了&#xff0c;例如授权需要分成好几行。如果想远程访问mysql&#xff0c;那么可以这样做&#xff1a; mysql -u root -p mysql //先登录mysql create user root% identified by 你自己的密码;//先建立一个root用户和密码 grant a…

Redis、memcache、MongoDB 对比

1. 数据结构和存储方式 Redis Redis 是一个开源的内存数据库&#xff0c;支持丰富的数据结构。它的数据类型包括&#xff1a; 字符串&#xff08;String&#xff09;哈希&#xff08;Hash&#xff09;列表&#xff08;List&#xff09;集合&#xff08;Set&#xff09;有序集…