算法day15|513.找树左下角的值、112. 路径总和、113.路径总和Ⅱ、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

本文主要是介绍算法day15|513.找树左下角的值、112. 路径总和、113.路径总和Ⅱ、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

算法day15|513.找树左下角的值、112. 路径总和、113.路径总和Ⅱ、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

  • 513.找树左下角的值
    • 迭代法
  • 112. 路径总和
  • 113.路径总和Ⅱ
  • 106.从中序与后序遍历序列构造二叉树
  • 105.从前序与中序遍历序列构造二叉树

513.找树左下角的值

一开始题意理解错了,做了好多无用功…看来读题真的非常重要。以为重点是左下角,其实题目的中的左下角必须是在最后一层。即使最后一层没有左孩子结点,只有右孩子结点,那么这个右孩子也算是树的左下角。

迭代法

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

迭代法我一开始也没有做出来,主要还是因为不知道该怎么去定位最后一层,我该凭什么逻辑来认定它就是最后一层呢?然后陷进去出不来了。而卡哥的解法非常巧妙:我们不管什么时候是最后一层,我先把一层里面第一个值赋给result。这样的话,第一层的第一个值赋给result,等到了的二层的时候机会自动更新为第二层的第一个值,第三层的时候以此类推… 所以当到了最后一层的时候,result就是最后一层的第一个值。只有对过程和结果的理解非常深刻才能想到这个。我们不单单看着最后一层,我们看到是整个逻辑过程

另外,除非思路贴吧清晰,否则不要使用while(n–),而要改用for(int i=0;i<n;i++)

112. 路径总和

这题还是比较简单的,代码如下:

class Solution {
public:void traversal(TreeNode*root,vector<int>&path,vector<int>& result){path.push_back(root->val);if(root->left==nullptr&&root->right==nullptr){int count=0;for(int i=0;i<path.size();i++)count+=path[i];result.push_back(count);return;}if(root->left){traversal(root->left,path,result);path.pop_back();}if(root->right){traversal(root->right,path,result);path.pop_back();}}bool hasPathSum(TreeNode* root, int targetSum) {vector<int> path;vector<int> result;int flag=false;if(root!=nullptr){traversal(root,path,result);for(int i=0;i<result.size();i++){if(result[i]==targetSum)flag=true;}}return flag;}
};

这题思路和257.二叉树的所有路径基本一致,只是把其中的一个字符串型数组改成了整数型数组,核心逻辑完全相同,属于模板题。

113.路径总和Ⅱ

这题同样很简单,只需要再加一个二位数组来接收一下路径即可。具体代码如下:

class Solution {
public:
void traversal(TreeNode*root,vector<int>&path,vector<int>& result,vector<vector<int>>&Path){path.push_back(root->val);if(root->left==nullptr&&root->right==nullptr){Path.push_back(path);int count=0;for(int i=0;i<path.size();i++)count+=path[i];result.push_back(count);return;}if(root->left){traversal(root->left,path,result,Path);path.pop_back();}if(root->right){traversal(root->right,path,result,Path);path.pop_back();}}vector<vector<int>> pathSum(TreeNode* root, int targetSum) {vector<int> path;vector<int> result;vector<vector<int>> Path;vector<vector<int>> Result;if(root!=nullptr){traversal(root,path,result,Path);for(int i=0;i<result.size();i++){if(result[i]==targetSum)Result.push_back(Path[i]);}}return Result;}
};

106.从中序与后序遍历序列构造二叉树

这题难度很大,而且其中的vector的用法我也是第一次见,一共花了一个多小时才弄明白,具体代码如下:

class Solution {
public:TreeNode*traversal(vector<int>& inorder, vector<int>& postorder){if(postorder.size()==0) return nullptr;int value=postorder[postorder.size()-1];TreeNode*root=new TreeNode(value);if(postorder.size()==1) return root;int index=0;for(;index<inorder.size();index++){if(inorder[index]==value) break;}vector<int>leftInorder(inorder.begin(),inorder.begin()+index);vector<int>rightInorder(inorder.begin()+index+1,inorder.end());postorder.resize(postorder.size()-1);vector<int>leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());vector<int>rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());root->left=traversal(leftInorder,leftPostorder);root->right=traversal(rightInorder,rightPostorder);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder){if(!inorder.empty())return traversal(inorder,postorder);elsereturn nullptr;}
};

总体思路(递归):

  • 参数显然是中序数组和后序数组,返回值是结点类型(这意味肯定有函数赋值的操作)

  • 终止条件,有2个:一是当后续数组为空时(每递归依次后序数组大小都会减一),返回null,比较正常;二是当后续数组只有一个元素时,直接返回root;(可以理解成剪枝的操作)

  • 单层递归:

    • 首先,先序遍历,创造当前结点空间并赋值(从当前节点往下走,因为孩子的递归需要父节点的信息,如怎么去切割,所有要先序遍历)。

    • 然后就是重头戏:为当前的左右孩子分别切割左右中序和左右后续

      • 先切割原来的中序数组。具体方法:定义两个vector数组,把左边的数组赋值到一个vector中,再把右边的数组赋值到另一个vector中;
      • 然后再切割后续数组。具体方法:把前面的和左中序相同大小的数组赋值到一个vector中,再把剩余的数组赋值到另一个vector中(在切割需要将原后序数组的大小减一)
      • 要注意,切割的时候要保证区间的统一,要么都是左开右闭,要不都是左闭右开等等,看情况选择一个,之后所有的区间都是按照这一个逻辑进行
    • 切割完成之后,给左孩子分配左中序和左后序,给右孩子分配有右中序和右后序,递归

    • 最后别忘了返回当前结点

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

class Solution {
public:TreeNode*traversal(vector<int>& preorder, vector<int>& inorder){if(preorder.size()==0)return nullptr;int value=preorder[0];TreeNode*root=new TreeNode(value);if(preorder.size()==1)return root;int index=0;for(;index<inorder.size();index++){if(inorder[index]==value)break;}vector<int> leftInorder(inorder.begin(),inorder.begin()+index);vector<int> rightInorder(inorder.begin()+index+1,inorder.end());preorder.erase(preorder.begin());vector<int> leftPreorder(preorder.begin(),preorder.begin()+leftInorder.size());vector<int> rightPreorder(preorder.begin()+leftInorder.size(),preorder.end());root->left=traversal(leftPreorder,leftInorder);root->right=traversal(rightPreorder,rightInorder);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if(!preorder.empty())return traversal(preorder,inorder);else return nullptr;}
};

原理基本相同,唯一不同的是先序数组要先删除第一个元素,而前面一题是删除最后一个元素。即preorder.erase(preorder.begin())。此函数内部包含了删除之后的数组位置的重新布置以及size–

这篇关于算法day15|513.找树左下角的值、112. 路径总和、113.路径总和Ⅱ、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1119667

相关文章

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

VSCode设置python SDK路径的实现步骤

《VSCode设置pythonSDK路径的实现步骤》本文主要介绍了VSCode设置pythonSDK路径的实现步骤,包括命令面板切换、settings.json配置、环境变量及虚拟环境处理,具有一定... 目录一、通过命令面板快速切换(推荐方法)二、通过 settings.json 配置(项目级/全局)三、

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键

如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)

《如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)》:本文主要介绍如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)问题,具有很好的参考价值,希望对大家有所帮助,如有... 目录先在你打算存放的地方建四个文件夹更改这四个路径就可以修改默认虚拟内存分页js文件的位置接下来从高级-

利用Python实现时间序列动量策略

《利用Python实现时间序列动量策略》时间序列动量策略作为量化交易领域中最为持久且被深入研究的策略类型之一,其核心理念相对简明:对于显示上升趋势的资产建立多头头寸,对于呈现下降趋势的资产建立空头头寸... 目录引言传统策略面临的风险管理挑战波动率调整机制:实现风险标准化策略实施的技术细节波动率调整的战略价

python进行while遍历的常见错误解析

《python进行while遍历的常见错误解析》在Python中选择合适的遍历方式需要综合考虑可读性、性能和具体需求,本文就来和大家讲解一下python中while遍历常见错误以及所有遍历方法的优缺点... 目录一、超出数组范围问题分析错误复现解决方法关键区别二、continue使用问题分析正确写法关键点三

一文详解如何查看本地MySQL的安装路径

《一文详解如何查看本地MySQL的安装路径》本地安装MySQL对于初学者或者开发人员来说是一项基础技能,但在安装过程中可能会遇到各种问题,:本文主要介绍如何查看本地MySQL安装路径的相关资料,需... 目录1. 如何查看本地mysql的安装路径1.1. 方法1:通过查询本地服务1.2. 方法2:通过MyS

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

《PostgreSQL序列(Sequence)与Oracle序列对比差异分析》PostgreSQL和Oracle都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,... 目录PostgreSQL 序列(Sequence) 与 oracle 序列对比一 基本语法对比1.1 创建序