LeetCode 热题 100 | 二叉树(四)

目录

1  114. 二叉树展开为链表

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

3  437. 路径总和 III


菜鸟做题(即将返校版),语言是 C++

1  114. 二叉树展开为链表

题眼:展开后的单链表应该与二叉树 先序遍历 顺序相同。

而先序遍历就是指,先遍历左子树,再遍历右子树。题意所说的展开,无非就是让左子树插队到右子树的前面去。

解题思路:采用递归,对于每个节点,先将它的左子树链到右侧去,再让右子树链到左子树的后面。

思路说明图:

对于节点 “1”,绿色部分为其左子树,黄色部分为其右子树。我们需要做的就是:先将左子树链到 “1” 的右侧去,再让右子树链到左子树的后面。对于节点 “2”,同理。

class Solution {
public:void flatten(TreeNode* root) {if (!root) return;TreeNode * p = root->left;if (p) {while (p->right) {p = p->right;}TreeNode * q = root->right;root->right = root->left;root->left = nullptr; // heap-use-after-free on address 0x503000000138p->right = q;}flatten(root->right);}
};

说明:为了能使右子树链到左子树的屁股后面,我们需要找到左子树的屁股,代码如下。

while (p->right) {p = p->right;
}

坑点:题目中说 “左子指针始终为 null”,即移走左子树后,要把左子指针置为空指针,代码如下。

root->left = nullptr; // heap-use-after-free on address 0x503000000138

否则会出现注释中的报错。

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

遍历特点:

  • 前序:根节点 << 左子树 << 右子树
  • 中序:左子树 << 根节点 << 右子树

因此,preorder 和 inorder 数组中的元素也呈现出上述排列规律。

思路说明图:

对于 preorder 数组,根据遍历特点,显然最左侧的 “3” 是根节点(root)。但是,我们无法根据 preorder 数组得知 “3” 的左子树和右子树分别是哪两坨。这时,inorder 数组就派上用场了。我们在 inorder 数组中定位 “3”,根据遍历特点,“3” 的左侧部分就是左子树(“9”),右侧部分就是右子树(“20” “15” “7”)。

现在,我们知道 “3” 的左子树和右子树分别是什么了,以及它们各自的长度。由此,我们可以在 preorder 数组中得到 “3” 的左子树和右子树所处的区间,即上图中的 绿色 部分和 蓝色 部分。又根据遍历特点,我们知道 绿色 部分的最左侧是左子树的根节点(root->left)蓝色 部分的最左侧是右子树的根节点(root->right)

以此类推,构造整个二叉树。

综上,preorder 数组的作用是定位各个根节点,inorder 数组的作用是定位左子树和右子树。

参数说明:

  • pre_left、pre_right:当前子树在 preorder 数组所处的区间
  • in_left、in_right:当前子树在 inorder 数组所处的区间
  • sub_ltree:左子树长度,帮助定位左子树区间
class Solution {
public:vector<int> preorder, inorder;unordered_map<int, int> hash;TreeNode * helper(int pre_left, int pre_right, int in_left, int in_right) {if (pre_left > pre_right) return nullptr;int pre_root = pre_left;int in_root = hash[preorder[pre_root]];int sub_ltree = in_root - in_left;TreeNode * node = new TreeNode(preorder[pre_root]);node->left = helper(pre_left + 1, pre_left + sub_ltree,in_left, in_root - 1);node->right = helper(pre_left + sub_ltree + 1, pre_right,in_root + 1, in_right);return node;}TreeNode* buildTree(vector<int>& arr1, vector<int>& arr2) {int n = arr1.size();preorder = arr1;inorder = arr2;for (int i = 0; i < n; ++i) {hash[inorder[i]] = i;}return helper(0, n - 1, 0, n - 1);}
};

3  437. 路径总和 III

关键字:深度搜索(先序遍历)+ 前缀和

我百度了一下,说它俩是一个意思。我觉得采用先序遍历是因为,它每次都是沿着一条直线去遍历的,而不是像中序遍历那样跳着遍历的。因此,先序遍历更符合题意。

思路说明图:路径 “5, 3” 的和可以看作是路径 “10, 5, 3” 的和减去路径 “10” 的和,也就是可以转换为字符串那一节的前缀和问题。

这里说的前缀是指以根节点为开始的路径,而前缀和就是各个前缀的路径和。

具体解法:

① 定义变量

  • hash 用于存放各个前缀的路径和
  • total 用于记录当前加总出的路径和
  • count 用于记录符合条件的路径和的个数

② 查询符合条件的路径和

if (hash.count(total - targetSum)) {count = hash[total - targetSum];
}

就是在 hash 表中寻找,是否有前缀的路径和与当前路径和的差为 targetSum 值。

③ 先序遍历

hash[total]++;
count += helper(root->left, total, targetSum);
count += helper(root->right, total, targetSum);
hash[total]--;

在走向下一个节点之前,先把当前路径和存入 hash 表中,因为它是前缀和。同时,当基于这条路径的所有路径都被遍历完毕后,要把这条路径的路径和移出 hash 表,即 hash[total]-- 。

比如,我们遍历完了节点 “3” 及其左右子树,接下来就该遍历 “5” 的右子树了。而 “5” 的右子树不会经过路径 “10, 5, 3” 。因此,在节点 “3” 发现自己的左右子树被遍历完时,“3” 就应该回收以自己为终点的路径 “10, 5, 3” 了。

class Solution {
public:unordered_map<long, int> hash;int helper(TreeNode * root, long total, int targetSum) {if (!root) return 0;int count = 0;total += root->val;if (hash.count(total - targetSum)) {count = hash[total - targetSum];}hash[total]++;count += helper(root->left, total, targetSum);count += helper(root->right, total, targetSum);hash[total]--;return count;}int pathSum(TreeNode* root, int targetSum) {hash[0] = 1;return helper(root, 0, targetSum);}
};

说明:下述代码是为了处理前缀本身的路径和等于 targetSum 的情况,也就是它(被减数)不需要和另一个前缀(减数)做减法。这里用路径和为 0 来表示减数,否则这种情况会被忽略。

hash[0] = 1;

题外话:虽然 count 变量在每一次递归中都是重新定义的,但是因为它是返回值,所以还是能起到计数器的作用。而 total 变量是作为参数一层一层传下去的,所以它也能起到计数器的作用。

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

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

相关文章

【编译原理】用Python实现LR(0)语法分析

实验内容 对于给定的如下文法&#xff0c;编写调试一个上下文无关文法的LR(0)分析程序。 文法G’为&#xff1a; S → E S\to E S→E E → a A E\to aA E→aA E → b B E \to bB E→bB A → c A A\to cA A→cA A → d A\to d A→d B → c B B\to cB B→cB B → d B\to …

网购商城系统源码 积分兑换商城系统源码 独立后台附教程

应用介绍 本文来自&#xff1a;网购商城系统源码 积分兑换商城系统源码 独立后台附教程 - 源码1688 简介&#xff1a; 网购商城系统源码 积分兑换商城系统源码 独立后台附教程 测试环境&#xff1a;NginxPHP7.0MySQL5.6thinkphp伪静态 图片&#xff1a;

软件实际应用实例,茶楼收银软件管理系统操作流程,茶室计时计费会员管理系统软件试用版教程

软件实际应用实例&#xff0c;茶楼收银软件管理系统操作流程&#xff0c;茶室计时计费会员管理系统软件试用版教程 一、前言 以下软件以 佳易王茶社计时计费管理系统软件V17.9为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、计时计费&…

JavaWeb——007MYSQL(DQL多表设计)

# 数据库开发-MySQL 一级目录二级目录三级目录 1. 数据库操作-DQL1.1 介绍1.2 语法1.3 基本查询1.4 条件查询1.5 聚合函数1.6 分组查询1.7 排序查询1.8 分页查询1.9 案例1.9.1 案例一1.9.2 案例二 2. 多表设计2.1 一对多2.1.1 表设计2.1.2 外键约束 2.2 一对一2.3 多对多2.4 案…

遥感影像目标检测:从CNN(Faster-RCNN)到Transformer(DETR)

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

vue或webpack加载highcharts与highcharts-3d

highcharts与highcharts-3d下载 https://jshare.com.cn/demos/hhhhiG 点击对应的文件可打开&#xff0c;复制代码到&#xff08;创建一个同名文件&#xff09;里面&#xff1b;放到项目对应目录下 引入 两种引入 highcharts.js 方法皆可用&#xff1b;注意 highcharts-3d 引入…

超全整理,自动化测试-YAML 配置文件深入解析(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、YAML详情 YAM…

Dear ImGui的UE5.3集成实践

Dear ImGui一直较为火热&#xff0c;这是一个调试使用并且可以响应快速迭代的Gui库&#xff0c;甚至可以做到在任何代码块中调用API即显示。如果你想更多的了解一下可访问其官方网站&#xff1a;https://www.dearimgui.org/ 那么本文就来在UE5中尝试踩坑使用它。 UE4.26版本 …

[引擎开发] 深入C++模板编程

[本文大纲] 引言 模板实例化 隐式实例化 显式实例化 模板具体化 显式具体化 部分具体化 函数重载和具体化 类型推断 隐式类型转换 支持的类型转换 引用和const 通用引用、引用折叠和完美转发 …

RDMA内核态函数ib_post_recv()源码分析

接上文&#xff0c;上文分析了内核rdma向发送队列添加发送请求的函数ib_post_send&#xff0c;本文分析一下向接收队列添加接收请求的函数ib_post_recv。其实函数调用流程与上文类似&#xff0c;不再重复说明&#xff0c;可参考链接。 函数调用过程 最终会调用到这个函数 下面…

浅谈数据分析工具在智慧城市中的作用

随着城市化、技术进步和人口不断增长&#xff0c;智慧城市已成为当今世界主要技术发展之一。 智慧城市设备依靠描述模型对城市环境产生的大量数据进行数据分析。 在这种城市景观中&#xff0c;智慧城市是技术和可持续的城市地区&#xff0c;利用信息和通信技术(ICT)来改善城市…

C语言每日一题(61)盛最多水的容器

题目链接 力扣 11 盛最多水的容器 题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水…

【服务发现--ingress】

1、ingress介绍 Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。 Ingress 是对集群中服务的外部访问进行管理的 API 对象&#xff0c;典型的访问方式是 HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟…

K线实战分析系列之十一:行情力量不足——平头形态

K线实战分析系列之十一&#xff1a;行情力量不足——平头形态 一、平头形态二、不同形态与平头形态的叠加三、总结平头形态 一、平头形态 前一根K线具有较长的实体&#xff0c;后一根K线的实体比较小&#xff0c;无论是多头还是空头的力量到第二根K线都被瓦解了多头上攻&#…

【数据结构与算法】(21)高级数据结构与算法设计之 Dynamic-Programming 动态规划算法 代码示例与详细讲解

目录 4.3 Dynamic-Programming1) Fibonacci降维 2) 最短路径 - Bellman-Ford3) 不同路径-Leetcode 62降维 4) 0-1 背包问题降维 5) 完全背包问题降维 6) 零钱兑换问题-Leetcode322降维零钱兑换 II-Leetcode 518 7) 钢条切割问题降维类似题目 Leetcode-343 整数拆分 8) 最长公共…

python 基础知识点(蓝桥杯python科目个人复习计划51)

今日复习计划&#xff1a;做复习题 例题1&#xff1a;大石头的搬运工 问题描述&#xff1a; 在一款名为“大石头的搬运工”的游戏中&#xff0c;玩家需要 操作一排n堆石头&#xff0c;进行n - 1轮游戏。 每一轮&#xff0c;玩家可以选择一堆石头&#xff0c;并将其移动到任…

【生活】浅浅记录

各位小伙伴们好鸭&#xff0c;今天不是技术文章&#xff0c;浅浅记录一下最近几个月的收获&#x1f60a; 新的一年&#xff0c;一起努力&#xff0c;加油加油&#xff01;

tinymce问题处理

Vite构建工具下Tinymce踩坑指南 解决方案是在路劲前面增加/&#xff0c;这个跟上面链接有些区别&#xff0c;区别原因应该是如果路由采用的是createWebHashHistory则应该去掉/&#xff0c;如果是createWebHistory则应该加上/ 页面引用,一种异步加载&#xff0c;一种同步加载&…

LeetCode 热题 100 | 二叉树(二)

目录 1 543. 二叉树的直径 2 102. 二叉树的层序遍历 3 108. 将有序数组转换为二叉搜索树 菜鸟做题&#xff0c;语言是 C 1 543. 二叉树的直径 这道题和 124. 二叉树中的最大路径和 太像了 题眼&#xff1a;二叉树的 直径 是指树中任意两个节点之间 最长路径的长度 。…

JS基础(三)-操作和流程控制

一 操作网页元素的步骤 1. 查找网页元素 给标签设置id属性&#xff0c;一个网页中的id值不允许重复 <button id"btn">按钮</button> 2. 给按钮绑定事件&#xff0c;监听用户操作 btn.onclick function(){ 一旦监听到用户的…