代码随想录算法训练营day18 | leetcode 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树
LeetCode 513.找树左下角的值
分析1.0
二叉树的 最底层 最左边 节点的值,层序遍历获取最后一层首个节点值,记录每一层的首个节点,当没有下一层时,返回这个节点
class Solution {
ArrayDeque<TreeNode> queue = new ArrayDeque();
int res = 0;
public int findBottomLeftValue(TreeNode root) {
queue.offer(root);
return levelOrder(root);
}
public int levelOrder(TreeNode p){
while(!queue.isEmpty()){
int size = queue.size();
int cnt = 0;
res = queue.peek().val;
// System.out.println("每层第一个节点"+res);
while(cnt++ < size){
p = queue.poll();
if(p.left != null){
queue.offer(p.left);
}
if(p.right != null){
queue.offer(p.right);
}
}
}
return res;
}
}
LeetCode 112. 路径总和
分析1.0
先序遍历递归,记录走过节点和,若==targetSum return; 否则删除节点值
递归
class Solution {
int sum = 0;
ArrayList<Integer> list = new ArrayList();
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null){
return false;
}
preOrder(root);
return list.contains(targetSum);
}
public void preOrder(TreeNode p){
sum += p.val;
if(p.left == null && p.right == null){
//System.out.println("sum--------"+sum);
list.add(sum);
return;
}
if(p.left!=null){
preOrder(p.left);
sum -= p.left.val;
}
if(p.right!=null){
preOrder(p.right);
sum -= p.right.val;
}
}
}
论递归有返回值时,某路径和为targetSum时,各级递归该如何返回
if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true;
count += cur->left->val; // 回溯,撤销处理结果
}
if (cur->right) { // 右
count -= cur->right->val; // 递归,处理节点;
if (traversal(cur->right, count)) return true;
count += cur->right->val; // 回溯,撤销处理结果
}
return false;
LeetCode 106.从中序与后序遍历序列构造二叉树
分析1.0
重要理论知识
切割后的左右子树,在前后序两个数组中元素大小是一致的
重要条件:
inorder和postorder都由 不同 的值组成
后序遍历 左右根 所以每棵树的后序数组的最后一个节点为树根
- 从后序数组找到这棵树的树根,用其分割中序数组,使原中序数组变为新的两个中序数组-即两棵子树
- 子树的大小是一致的,即可利用此特点在后序数组中找到两棵树分别对应的后序遍历序列 第一个是左子树 第二个是右子树 顺序不要弄反
- 再从后序序列获取新的根节点...
- ......
- 直到后序数组只剩一个节点,处理完这个节点就返回
getInIndex(); return 两棵子树在中序数组中的索引
getPostIndex(); return 左右子树的新的根节点索引 左边一堆为左子树 右边一堆为右子树
失误
没课树都有post in order,当postOrder只剩一个节点时,意味着这棵树只有一个根节点了,让它做父节点合适的儿子
递归前要进行一次判断,这个节点能否满足递归条件
分析2.0
class Solution {
//int testCount = 1;
public TreeNode buildTree(int[] inorder, int[] postorder) {
return getRootIndex(inorder, postorder, 0, inorder.length - 1, 0, postorder.length-1);
}
public TreeNode getRootIndex(int[] inorder, int[] postorder, int inLeftIndex, int inRightIndex,int postLeftIndex,int postRightIndex){
//System.out.println(testCount++ +"次访问");
// 只剩一个后序节点了
if(postRightIndex==postLeftIndex){
return new TreeNode(postorder[postRightIndex]);
}
// 后序根节点在中序中的索引
int mid = getIndex(inorder, postorder[postRightIndex]);
// 左子树中序新索引范围
int leftTreeLeftIndex = inLeftIndex;
int leftTreeRightIndex = mid-1;
// 右子树中序新索引范围
int rightTreeLeftIndex = mid+1;
int rightTreeRightIndex = inRightIndex;
/* 找左右子树的后序索引范围
左子树-右子树-根节点
左子树 leftTreeRightIndex - leftTreeLeftIndex + 1
右子树 rightTReeRightIndex - rightTreeLeftIndex + 1
*/
//int leftTreeSize = leftTreeRightIndex - leftTreeLeftIndex + 1;
int rightTreeSize = rightTreeRightIndex - rightTreeLeftIndex + 1;
int leftTreePostOrderLeftIndex = postLeftIndex;
int leftTreePostOrderRightIndex = postRightIndex - rightTreeSize - 1;
int rightTreePostOrderLeftIndex = postRightIndex - rightTreeSize;
int rightTreePostOrderRightIndex = postRightIndex - 1;
TreeNode root = new TreeNode(postorder[postRightIndex]);
if(leftTreePostOrderRightIndex>=leftTreePostOrderLeftIndex){
root.left = getRootIndex(inorder, postorder,leftTreeLeftIndex, leftTreeRightIndex,leftTreePostOrderLeftIndex,leftTreePostOrderRightIndex);
}
if(rightTreePostOrderRightIndex>=rightTreePostOrderLeftIndex){
root.right = getRootIndex(inorder, postorder,rightTreeLeftIndex, rightTreeRightIndex,rightTreePostOrderLeftIndex,rightTreePostOrderRightIndex);
}
return root;
}
// 在指定数组中找指定元素的索引
public int getIndex(int[] arr, int target){
for(int i = 0; i < arr.length; i++){
if(arr[i] == target){
return i;
}
}
return -1;
}
}
总结
递归函数什么时候需要返回值?什么时候不需要返回值?视递归是否需要处理返回值分析
和单纯的深度遍历不一样,在处理树回溯问题时要先判断当前节点是否为空,非null才能进入递归
- 如果知道了目标和,可以目标和-节点值,判断最后结果是否为0 (而不是累加节点值判断和是否为目标和)
- 回溯结束就可以处理返回值了!!!
- 递归进入条件、递归结束条件
- 树的先序后序遍历序列对应的节点数是一致的 非常关键的解题信息
常用变量名增量更新
size、val、ans、cnt、cur、pre、next、left、right、index、gap、tar、res、src、len、start、end、flag、ch、var
代码随想录算法训练营day18 | leetcode 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树的更多相关文章
- LeetCode 513. 找树左下角的值(Find Bottom Left Tree Value)
513. 找树左下角的值 513. Find Bottom Left Tree Value 题目描述 给定一个二叉树,在树的最后一行找到最左边的值. LeetCode513. Find Bottom ...
- Java实现 LeetCode 513 找树左下角的值
513. 找树左下角的值 给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输 ...
- Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value)
Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,在树的最后一行找到最 ...
- 领扣(LeetCode)找树左下角的值 个人题解
给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 注意: 您可以假 ...
- Leetcode:105. 从前序与中序遍历序列构造二叉树&106. 从中序与后序遍历序列构造二叉树
Leetcode:105. 从前序与中序遍历序列构造二叉树&106. 从中序与后序遍历序列构造二叉树 Leetcode:105. 从前序与中序遍历序列构造二叉树&106. 从中序与后序 ...
- [LeetCode]105. 从前序与中序遍历序列构造二叉树(递归)、108. 将有序数组转换为二叉搜索树(递归、二分)
题目 05. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 题解 使用HashMap记录当前子树根节点在中序遍历中的位置,方便每次 ...
- 【LeetCode】105. Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcod ...
- LeetCode(106):从中序与后序遍历序列构造二叉树
Medium! 题目描述: 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 posto ...
- [LeetCode系列] 从中序遍历和后序遍历序列构造二叉树(迭代解法)
给定中序遍历inorder和后序遍历postorder, 请构造出二叉树. 算法思路: 设后序遍历为po, 中序遍历为io. 首先取出po的最后一个节点作为根节点, 同时将这个节点入stn栈; 随后比 ...
- Leetcode 106. 从中序与后序遍历序列构造二叉树
题目链接 https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/descri ...
随机推荐
- editorial 专栏
社论 22.10.1 solution for pl_er 密码是我的名字的拼音 全小写无空格 社论 22.10.2 solution for Simu. 密码是联考密码 社论 22.10.4 sol ...
- 论文解读(PCL)《Probabilistic Contrastive Learning for Domain Adaptation》
论文信息 论文标题:Probabilistic Contrastive Learning for Domain Adaptation论文作者:Junjie Li, Yixin Zhang, Zilei ...
- STM32基本定时器控制LED闪烁代码
led.c #include "led.h" void LED_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2P ...
- MS17-010漏洞复现(永恒之蓝)
0x01:温馨提示 微软已于2017 年 发布MS17-010补丁,修复了"永恒之蓝"攻击的系统漏洞,一定要及时更新Windows系统补丁. 本次只是简易的复现MS17-010,成 ...
- C#应用程序配置文件(XML序列化) - 开源研究系列文章
上次写了一个C#线程池及管理器的博文( C#开发的线程池和管理器 - 开源研究系列文章 ),收到了不小的浏览量,在此感谢各位网友的支持.这次将另一个功能放出来单独讲解:C#应用程序的配置文件,使用的是 ...
- python进阶之路8 字典、元组、集合内置方法 编码理论
内容回顾 作业讲解 1.前期不熟练的情况下一定要先写注释 2.一定要仔细思考每一行代码的含义 3.自己不会的代码或者不熟练的代码一定要多敲多练 数据类型内置方法简介 所有的数据类型基本上都自带了一些操 ...
- Angularjs的工程化
Angularjs的工程化 AMD规范和CMD规范 为什么需要模块化管理工具 在编写项目时可能需要加载很多js文件,若b.js依赖a.js,且a.js比b.js大很多,那么浏览器会让b.js等待a.j ...
- Spring Native打包本地镜像,无需通过Graal的maven插件buildtools
简介 在文章<GraalVM和Spring Native尝鲜,一步步让Springboot启动飞起来,66ms完成启动>中,我们介绍了如何使用Spring Native和buildtool ...
- C#移除字符串中的不可见Unicode字符
背景 最近发现某个数据采集的系统拿下来的数据,有些字段的JSON被莫名截断了,导致后续数据分析的时候解析JSON失败. 类似这样 {"title": "你好 或者这样,多 ...
- 行为型模式 - 观察者模式Observer
学习而来,代码是自己敲的.也有些自己的理解在里边,有问题希望大家指出. 有一个大佬视频中提过一个案例,我觉得很棒:遥闻深巷中犬吠,边有妇人惊觉欠伸,其夫呓语.继而儿醒,大啼.夫亦醒. 模式的定义与特点 ...