《代码随想录(Carl)》 数据结构与算法 题目解法关键知识点记录(二)

文章详细梳理了LeetCode中关于数据结构与算法的二叉树题目,涵盖了前序、中序、后序遍历,以及N叉树的遍历方法。此外,还包括二叉树的深度、平衡性、路径和搜索等相关问题,强调了不同遍历策略在解决二叉树问题中的应用,并提供了多种解题方法。通过这些题目,读者可以系统地学习和提升在二叉树和算法方面的知识和技能。
摘要由CSDN通过智能技术生成

《代码随想录(Carl)》 数据结构与算法

一数据结构类题目

1.6 Binary Tree

1.144. 二叉树的前序遍历【循环前序+统一循环前序+递归前序】
2.94. 二叉树的中序遍历【统一循环中序+递归中序】
3.145. 二叉树的后序遍历【统一循环后序+递归后序】
4.589. N 叉树的前序遍历【统一循环前序+递归前序】
5.590. N 叉树的后序遍历【统一循环后序+递归后序】
6.102. 二叉树的层序遍历
7.107. 二叉树的层次遍历II【最后把result向量反转一下】
8.199. 二叉树的右视图【每层最后一个元素放入result向量中】
9.637. 二叉树的层平均值【每一层元素计算平均值】
10.429. N 叉树的层序遍历【子节点向量】
11.515. 在每个树行中找最大值【定义每行最大值变量时初始化为最小值std::numeric_limits::min()】
12.116. 填充每个节点的下一个右侧节点指针【满二叉树,本层前一个节点的next指针指向本节点】
13.117. 填充每个节点的下一个右侧节点指针 II【普通二叉树,解法同116】
14.226. 翻转二叉树【统一循环前中后序+递归前后序+层序遍历都可以,唯独递归中序遍历不行,左右子节点交换两次。遍历的过程中翻转每一个节点的左右两个子节点就可以达到翻转整个二叉树的效果。】
15.101. 对称二叉树【递归中序全部遍历完+循环层序遍历+首尾双指针判断对称节点是否相等;本质是判断左右子树是否可翻转+递归后序遍历(两节点不为空且数值相等则继续递归遍历外内侧子节点)+循环queue/stack按层遍历】
16.104. 二叉树的最大深度【统一循环(110. 平衡二叉树P73记录从上到下遍历时的最大深度)/递归后序遍历+层序遍历+递归前序遍历(110. 平衡二叉树P69) (回溯隐藏在递归函数调用的参数赋值里);循环/递归前序遍历+回溯(OfferV2No34)】
17.559. N 叉树的最大深度【统一循环(104. 二叉树的最大深度P73)/递归后序遍历+层序遍历】
18.110. 平衡二叉树【统一循环/递归后序遍历;统一循环后序遍历(104. 二叉树的最大深度P73)+循环前序遍历(统一循环/递归前中后序遍历)】
19.111. 二叉树的最小深度【统一循环(104. 二叉树的最大深度P73)/递归后序遍历(第一个叶节点深度赋值给max_depth/二叉树的所有节点都没有左子树,左子树深度为0,树的深度为从下向上右子树深度加1) +层序遍历(最先遍历到叶节点的层数) ;循环/递归前序遍历+回溯(OfferV2No34)】
20.257. 二叉树的所有路径【循环前序遍历(栈存储路径字符串-按照遍历节点递增,返回vector);递归前序遍历+回溯(返回到父节点再回溯,路径字符串path增加后赋值给递归函数的参数,函数调用结束path不变(精简版));循环/递归前序遍历+回溯(OfferV2No34)(遍历本节点结束时回溯)】
21.112. 路径总和【循环前序遍历(遍历节点和包括节点的路径和的pair放入栈中);递归前序遍历+回溯(递归函数内没有中节点处理逻辑,count减去中节点数值的处理逻辑放在了函数入参处);】
22.113. 路径总和 II【就是OfferV2No34题目,循环/递归前序遍历+回溯 (遍历本节点结束时回溯vector<vector>) ;与(257. 二叉树的所有路径)相似,递归前序遍历+回溯(count减去中节点数值的处理逻辑放在了函数入参处,返回到父节点再回溯) ;】
23.222. 完全二叉树的节点个数【统一循环(110. 平衡二叉树P73记录处理节点时统计节点个数)/递归后序遍历+层序遍历;完全二叉树性质:递归寻找满二叉树,利用公式计算满二叉树节点个数;递归前序遍历(O(logn * logn)+O(logn), (2 << leftHeight) - 1)】
24.404. 左叶子之和【循环前序遍历+统一循环前中后序遍历+层序遍历+递归后序遍历(判断本节点的左孩子是否为左叶子节点,通过本节点的左孩子节点的左右子节点,判断本节点的左孩子是否为左叶子节点);循环前序遍历+标记(OfferV2No34) +递归前序遍历(左节点是叶子节点:通过节点的左孩⼦判断本节点的属性)】
25.513. 找树左下角的值【递归前序遍历+回溯:最大深度的第一个叶节点+层序遍历(变量记录每行第一个节点值,下一行更新)】
26.106. 从中序与后序遍历序列构造二叉树【用序列值构造二叉树节点;将递归函数内创建的二叉树节点指针作为返回值;下标索引优化版:切割中序数组,找到切割点(后序数组的最后⼀个元素)在中序数组的位置,然后按照切割点前后进行将中序数组切割为左中序数组和右中序数组;那么后序数组就可以按照左中序数组的⼤⼩来切割,从前到后连续切成左后序数组和右后序数组。】
27.654. 最大二叉树【类中序序列构建二叉树,采用下表索引优化版,左闭右闭时的边界值处理;左闭右闭无法判断输入的向量元素个数是否为0,所以向下递归时要保证左右子向量元素个数至少为1】
28.617. 合并二叉树【递归前序遍历(也可新建二叉树)+循环queue层序遍历(利用原来t1的二叉树连接结构,修改t1二叉树节点值或节点左右子节点的指针指向)】
29.700. 二叉搜索树中的搜索【递归和循环遍历二叉搜索树都是单向搜索,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的⽅向。】
30.98. 验证二叉搜索树【if条件判断if (root->left && root->right)左右子节点都不为空时成立;二叉搜索树中不能有重复元素;统一循环/递归中序遍历-全局变量或二叉树节点指针记录上一个节点大于等于当前遍历节点值返回false(根据中序遍历的顺序特点,只需要利用全局节点指针记录前一个节点,比较前一个节点和当前节点的大小;自己思路中利用递归后序遍历处理当前节点要与左子树最大值比较,还要与右子树的最小值比较,相对比较麻烦,没有利用二叉树的有序性特点和中序遍历的特点);边界值处理,二叉搜索树中不能有相等的元素,定义最小值全局变量为std::numeric_limits::min(),防止与二叉搜索树节点值std::numeric_limits::min()相同】
31.530. 二叉搜索树的最小绝对差【统一循环/递归中序遍历-全局变量或二叉树节点指针记录上一个节点与当前节点差值的绝对值的最小值;边界值处理,定义差值绝对值的最小值为std::numeric_limits::min(),防止二叉搜索树节点差值绝对值超出std::numeric_limits范围】
32.501. 二叉搜索树中的众数【统一循环/递归中序遍历二叉(搜索)树,unordered_map统计元素频率O(n),优先级队列priority_queue构造大顶堆/用map构造相同pair元素的vector用sort从大到小-对频率进行排序O(nlogn),提取队列出口频率最大的元素放进result;统一循环/递归中序一次遍历二叉搜索树,处理节点时[采用二叉树节点指针pre记录上一个节点和当前遍历节点cur进行比较的技巧]统计出现频率最大的元素,不断在result向量里更新O(n)】
33.538. 把二叉搜索树转换为累加树【换⼀个⻆度来看,这就是⼀个有序数组[2, 5, 13],求从后到前的累
加数组,也就是[20, 18, 13]。在二叉搜索树中累加的顺序是右中左,所以我们需要反中序遍历这个⼆叉树,然后顺序累加就可以了;统一循环/递归反向中序遍历,采用二叉树节点指针pre记录上一个节点,当前遍历节点cur的值加上pre前一个节点的值】
34.701. 二叉搜索树中的插入操作【统一循环中序遍历,采用二叉树节点指针pre记录上一个节点,和当前遍历节点cur的值共同与val进行比较,构建val节点插入二叉搜索树中。注意第一个节点,最后一个节点,根节点为nullptr的边界特殊用;递归中序遍历如何知道是遍历或处理的最后一个节点;如何通过递归函数返回值完成了新加⼊节点的⽗⼦关系赋值操作:下⼀层将加⼊节点返回,本层⽤root->left或者root->right将其接住。循环搜索查询需要记录上⼀个节点(parent),遇到空节点了,就让parent左孩⼦或者右孩⼦指向新插⼊的节点。】
35.450. 删除二叉搜索树中的节点【循环查找待删除的目标节点和前pre_node后next_node节点,按照目标节点的左target_node->left右target_node->right子节点是否为空,前后节点是否为目标节点左右子节点、叶节点以及带有pre_left或next_right的中间节点三大类,目标节点是否为根节点两小类的分类都考虑全了;
递归前序遍历查找待删除的目标节点,递归返回值删除目标节点:针对目标节点左右子节点都不为空的情况,将左子树挪到next_node的左子节点处,删除目标节点保留左右子树,将删除目标节点后的新的当前节点返回给上一层父节点的指针;
循环查找待删除的目标节点和后next_node节点,需要⼀个pre记录cur的⽗节点,⽅便做删除操作,模拟递归法中的逻辑来删除节点,删除节点子函数逻辑与递归单层逻辑相同;】
36.669. 修剪二叉搜索树【递归前序遍历查找不符合区间要求的目标节点,递归返回值删除目标节点:目标节点值小于区间时递归右子树继续寻找符合区间要求的新节点,通过返回值传回本层替代root,删除目标节点及左子树,目标节点值大于区间时递归左子树继续寻找符合区间要求的新节点,通过返回值传回本层替代root,删除目标节点及右子树,将删除目标节点后的新的符合区间要求的当前节点root返回给上一层父节点的指针;循环移动root到[L,R]区间内和剪枝左右子树,剪枝左子树:左子节点cur->left值小于区间,cur->left->left为根节点的左子树值全部小于cur->left,所以cur->left和左子树全部都不要了,cur->left->right作为新的cur->left节点,继续遍历左子节点进行剪枝。】
37.108. 将有序数组转换为二叉搜索树【递归前序二分构建中点节点,构建二叉平衡树,递归终止条件与空向量是否继续递归相匹配;循环层序二分构建中点节点,从上到下按层构建二叉平衡树(层序遍历思想);】
38.236. 二叉树的最近公共祖先【循环前序遍历+标记法回溯 获得p和q结尾的两个路径向量,找到最后一个相同的元素;递归后序遍历实现从叶节点向上的遍历方式进行回溯;由于回溯时后序遍历中节点逻辑处理要使用递归函数的返回值left和right做判断,不能立刻返回,需要等left和right逻辑处理完之后才能返回,所以依然要遍历整棵树;回溯逻辑处理分4种情况将结果返回给头结点;】
39.235. 二叉搜索树的最近公共祖先【二叉搜索树⾃带⽅向性,可以⽅便的从上向下查找⽬标区间,遇到⽬标区间内的节点,直接返回。循环/递归查找最近公共祖先,利用了二叉搜索树的节点值有序性;】

感谢Carl对于LeetCode中的数据结构与算法题目的系统讲解工作,可查看网页 linkhttps://programmercarl.com
linkhttps://github.com/youngyangyang04/leetcode-master 中的讲解文档。
按照类型从基础到提高循序渐进的过程选择经典题目高频面试题来讲解,大大提高了学习数据结构与算法知识和刷题效率,解决了浪费的时间主要三个问题点:1找题;2找到了不应该现阶段做的题;3没有全套的优质题解可以参考。
按照如下类型来练习:数组-> 链表-> 哈希表->字符串->栈与队列->树->回溯->贪心->动态规划->图论->高级数据结构,从简单刷起,做了几个类型题目之后,再慢慢做中等题目、困难题目。
经过系统的知识学习和技能练习现对整个知识体系的掌握有了一个质的飞跃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值