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

leetcode hot100 二叉树(二)

书接上回:https://blog.csdn.net/weixin_74129837/article/details/148367615?spm=1001.2014.3001.5501

8.验证二叉搜索树

维护一个min_val和max_val,限制当前结点的合法值范围。min_val和max_val动态变化。

class Solution {
public:bool check(TreeNode* node,long min_val,long max_val){if(!node) return true;if(node->val<=min_val||node->val>=max_val) return false;  //注意定义,等于也不行return check(node->left,min_val,node->val)&&check(node->right,node->val,max_val);}bool isValidBST(TreeNode* root) {return check(root,LONG_MIN,LONG_MAX);}
};

9.二叉搜索树中第k小的元素

在BST中,中序遍历(左-根-右)会按升序访问所有节点

因此,第k个被访问的节点就是第k小的元素。

代码本质上是迭代实现的中序遍历,并通过提前终止(剪枝)来优化。

算法流程:向左深入->回溯到父结点->转向右子树。

class Solution {
public:int kthSmallest(TreeNode* root, int k) {stack<TreeNode*> stk;while(root||stk.size()){while(root){stk.push(root);  root=root->left;} root=stk.top();  //取出最后遍历到的父结点(相当于回溯)stk.pop();if(--k==0) return root->val;root=root->right;}return root->val;}
};

10.二叉树的右视图

dfs遍历,且优先遍历右子树。

如果层数==res大小,说明当前层还未加入结点,即本次递归到的结点是当前层右数第一个结点。

class Solution {
public:void dfs(TreeNode* root,vector<int>& res,int u){if(!root) return ;//在搜索过程中总是先访问右子树//对于每一层来说,这层见到的第一个结点一定是最右边的结点//u==res.size()时,当前层级u还没有被记录到res中(res 的索引是0到u-1,共u层)if(u==res.size()) res.push_back(root->val);dfs(root->right,res,u+1);dfs(root->left,res,u+1); }vector<int> rightSideView(TreeNode* root) {vector<int> res;if(!root) return res;dfs(root,res,0);return res;}
};

 11.二叉树展开为链表

核心:展开的单链表与二叉树先序遍历的顺序相同。

class Solution {
public:void flatten(TreeNode* root) {vector<TreeNode*> nodes; // 用于存储先序遍历的结果preorderTraversal(root,nodes); // 获取先序遍历结果int n=nodes.size();for (int i=1;i<n;i++){TreeNode* prev=nodes[i-1];TreeNode* curr=nodes[i];prev->left=nullptr; // 左子指针置空prev->right=curr;   // 右子指针指向下个节点}}//先序遍历:根->左->右void preorderTraversal(TreeNode* root,vector<TreeNode*> &l){if(root){l.push_back(root);preorderTraversal(root->left,l);preorderTraversal(root->right,l);}}
};

12.从前序与中序遍历序列构造二叉树

class Solution {
private:unordered_map<int,int> index;
public:TreeNode* build(vector<int>& pre,vector<int>& in,int pre_left,int pre_right,int in_left,int in_right){if(pre_left>pre_right) return nullptr;int pre_root=pre_left;  //pre_root是索引int in_root=index[pre[pre_root]];int left_size=in_root-in_left;TreeNode* root=new TreeNode(pre[pre_root]);root->left=build(pre,in,pre_left+1,pre_left+left_size,in_left,in_root-1);root->right=build(pre,in,pre_left+left_size+1,pre_right,in_root+1,in_right);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {int n=preorder.size();for(int i=0;i<n;i++) index[inorder[i]]=i;return build(preorder,inorder,0,n-1,0,n-1);}
};

13.路径总和

        如图,先利用先序遍历序列确定根节点,再利用中序遍历序列递归子树,关键是递归边界的确定。

class Solution {
public:int dfs(TreeNode* node,long sum,int target){if(!node) return 0;int cnt=0;if(sum+node->val==target) cnt++;cnt+=dfs(node->left,sum+node->val,target);cnt+=dfs(node->right,sum+node->val,target);return cnt;} int pathSum(TreeNode* root, int targetSum) {if(!root) return 0;int cnt=dfs(root,0,targetSum);cnt+=pathSum(root->left,targetSum);cnt+=pathSum(root->right,targetSum);return cnt;}
};

14.二叉树的最近公共祖先

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(!root) return nullptr;if(p==root||q==root) return root;TreeNode* left=lowestCommonAncestor(root->left,p,q);TreeNode* right=lowestCommonAncestor(root->right,p,q);if(right&&left) return root;  //左右节点都有,最近公共祖先是根结点if(left) return left;  //只有左结点if(right) return right;  //只有右结点return nullptr;}
};

15.二叉树的最大路径和

  • 后序遍历:采用DFS的后序遍历方式(左右根)来遍历整棵树。
  • 计算单边最大增益:对于每个节点,计算其左子树和右子树能提供的最大增益(如果增益为负则取0,表示不选择该子树)。
  • 更新全局最大值:对于当前节点,计算包含该节点及其左右子树的最大路径和(即node->val + left_gain + right_gain),并更新全局最大值max_sum
  • 返回单边最大路径:向上返回时只能选择左或右子树中增益较大的一边加上当前节点的值。
class Solution {
public:int dfs(TreeNode* node,int& max_sum){if(!node) return 0;int left_gain=max(dfs(node->left,max_sum),0);int right_gain=max(dfs(node->right,max_sum),0);int curr_sum=node->val+left_gain+right_gain;max_sum=max(max_sum,curr_sum);return node->val+max(left_gain,right_gain);}int maxPathSum(TreeNode* root) {int max_sum=INT_MIN;dfs(root,max_sum);return max_sum;}
};

http://www.xdnf.cn/news/10704.html

相关文章:

  • 项目采购管理习题剖析
  • SystemVerilog—Interface语法(一)
  • 【多线程初阶】内存可见性问题 volatile
  • ps颜色查找修改
  • QT动画类
  • 使用 Haproxy 搭建高可用 Web 群集
  • 守护进程导致程序kill掉后被重新拉起
  • Java集合初始化:Lists.newArrayList vs new ArrayList()
  • 线程安全 — 场景、解决、悲观锁、乐观锁
  • mysql离线安装教程
  • 计算机视觉NeRF
  • 【GESP真题解析】第 6 集 GESP 三级 2023 年 9 月编程题 1:小杨的储蓄
  • 电路图识图基础知识-高、低压供配电系统电气系统的继电自动装置(十三)
  • android binder(三)binder.c函数分析
  • 审计- 1- 审计概述
  • Python-matplotlib中的Pyplot API和面向对象 API
  • UE5 创建2D角色帧动画学习笔记
  • 网络节点排查
  • RAG系统中如何检测幻觉?
  • 【dshow】VIDEOINFOHEADER2 头文件
  • Arch安装megaton
  • PHP7+MySQL5.6 查立得轻量级公交查询系统
  • ck-editor5的研究 (5):优化-页面离开时提醒保存,顺便了解一下 Editor的生命周期 和 6大编辑器类型
  • 【LeetCode 题解】两数之和(C++/Python 双解法):从语法到算法的全面解析
  • #14 学习日志
  • ②Pybullet干涉检查指令getContactPoints与 getClosestPoints介绍
  • Vue-5-基于JavaScript和plotly.js绘制数据分析类图表
  • ubuntu22.04安装megaton
  • 图像任务中的并发处理:线程池、Ray、Celery 和 asyncio 的比较
  • 经典数学教材推荐(AI相关)