6.二叉树.题目2

6.二叉树.题目2

  • 题目
    • 9.找树左下角的值
    • 10.路径总和
    • 11.从中序与后序遍历序列构造二叉树
    • 12.最大二叉树
    • 13.合并二叉树
    • 14.二叉搜索树中的搜索
    • 15.验证二叉搜索树
    • 16.二叉搜索树的最小绝对差
  • 总结

题目

9.找树左下角的值

题目链接
给定一个二叉树,在树的最后一行找到最左边的值。此时可以想到使用层序遍历会非常简单,也是十分自然的。但也可以使用递归来解决(后序再进行补充),但会麻烦一点。

广度优先-迭代法

    int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);int result = 0;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;}

10.路径总和

题目链接
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。这题可以看作是7.二叉树的所有路径题目的扩展
递归法-前中后序都可以

  • 确定递归函数的参数&返回类型:需要二叉树的根节点,需要一个计数器(用来计算二叉树的一条边之和是否等于目标和);递归函数返回类型是bool。
  • 终止条件:当遍历到叶子节点时候的判断
    bool traversal(TreeNode* cur, int count){if(!cur->left&&!cur->right && count==0) return true;if(!cur->left&&!cur->right) return false;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;}bool hasPathSum(TreeNode* root, int targetSum) {if(root==nullptr) return false;return traversal(root, targetSum-root->val);}

深度遍历-迭代法
此时栈里一个元素不仅要记录该节点的指针,还要记录从根节点到该节点的数值之和,因此需要用到std::pair<TreeNode*, int>的数据类型,加入到栈的遍历中。

    bool haspathsum(TreeNode* root, int sum) {if (root == null) return false;// 此时栈里要放的是pair<节点指针,路径数值>stack<pair<TreeNode*, int>> st;st.push(pair<TreeNode*, int>(root, root->val));while (!st.empty()) {pair<TreeNode*, int> node = st.top();st.pop();if (!node.first->left && !node.first->right && sum == node.second) return true;if (node.first->right) {st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));}if (node.first->left) {st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));}}return false;} 

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

题目链接
根据一棵树的中序遍历与后序遍历构造二叉树,注意你可以假设树中没有重复的元素。
例如给出中序遍历 inorder = [9,3,15,20,7];后序遍历 postorder = [9,15,7,20,3];需要你返回:
在这里插入图片描述
根据总结里面提到的切割法:1.判断数组是否非空 2.若非空,取出后序数组最后一个数值作为新节点的值 3.用该值对中序数组进行切割(不包含切割点)4.根据切完的左子中序数组的大小对后序数组进行切割(不包含最后一个数值)5.得到新的子中序数组,后续数组 ,进入下一层递归。

    TreeNode* traversal(std::vector<int> inorder, int in_begin, int in_end, std::vector<int> postorder, int post_begin, int post_end){if(post_begin==post_end) return nullptr;int rootvalue = postorder[post_end-1];TreeNode* root = new TreeNode(rootvalue);if(post_end-post_begin==1) return root;// 获取中序数组切割点索引-根据后续数组的最后一个数值int delimiterIndex;for(delimiterIndex=in_begin; delimiterIndex<in_end; delimiterIndex++){if(inorder[delimiterIndex]==rootvalue) break;}// 切割-以左闭右开的形式存储数值// 切割中序数组的切割点是不保留的int left_in_begin = in_begin;int left_in_end = delimiterIndex;int right_in_begin = delimiterIndex + 1;int right_in_end = in_end;// 根据切割完的左子后序数组的数量进行切割后序数组,不保留最后一个数值int left_post_begin = post_begin;int left_post_end = post_begin + left_in_end - left_in_begin;int right_post_begin = post_begin + left_in_end - left_in_begin;int right_post_end = post_end-1;root->left = traversal(inorder, left_in_begin, left_in_end, postorder, left_post_begin, left_post_end);root->right = traversal(inorder, right_in_begin, right_in_end, postorder, right_post_begin, right_post_end);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if(inorder.size()==0 || postorder.size()==0) return nullptr;return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());}

从前序与中序遍历序列构造二叉树
题目链接


12.最大二叉树

题目链接
给定一个不含重复元素的整数数组,一个以此数组构建的最大二叉树定义如下:

  • 二叉树的根是数组中的最大元素。
  • 左子树是通过数组中最大值左边部分构造出的最大二叉树。
  • 右子树是通过数组中最大值右边部分构造出的最大二叉树。

构造树一般采用前序遍历,因为先构造中间节点,再构造左,右子节点。 这题可以使用递归法来解决,类似寻找切割点,构建节点,切割数组得到左右子数组,进入下一层迭代。

    TreeNode* travesal(std::vector<int>& nums, int left, int right){if(left>=right) return nullptr;int maxvalueindex = left;for(int i = left+1; i<right; i++){if(nums[i]>nums[maxvalueindex]) maxvalueindex = i;}TreeNode* root = new TreeNode(nums[maxvalueindex]);root->left = travesal(nums, left, maxvalueindex);root->right = travesal(nums, maxvalueindex+1, right);return root;}TreeNode* constructMaximumBinaryTree(vector<int>& nums) {return travesal(nums, 0, nums.size());}

13.合并二叉树

(题目链接)
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
在这里插入图片描述
递归法-在了解回溯算法后比较容易理解

// 前序法TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1// 修改了t1的数值和结构t1->val += t2->val;                             // 中t1->left = mergeTrees(t1->left, t2->left);      // 左t1->right = mergeTrees(t1->right, t2->right);   // 右return t1;}

迭代法-常规使用stack堆存储要遍历的元素


14.二叉搜索树中的搜索

(题目链接)
给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
重新复习搜索二叉树

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树

递归法

    TreeNode* searchBST(TreeNode* root, int val) {if (root == NULL || root->val == val) return root;TreeNode* result = NULL;if (root->val > val) result = searchBST(root->left, val);if (root->val < val) result = searchBST(root->right, val);return result;}

迭代法
对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法;对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的

    TreeNode* searchBST(TreeNode* root, int val) {while (root != NULL) {if (root->val > val) root = root->left;else if (root->val < val) root = root->right;else return root;}return NULL;}

因为二叉搜索树的有序性,遍历的时候要比普通二叉树简单很多。


15.验证二叉搜索树

(题目链接)
给定一个二叉树,判断其是否是一个有效的二叉搜索树。即检查该二叉树是否满足二叉搜索树的定义。
中序遍历下,输出的二叉搜索树节点的数值是有序序列。验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。
递归

private:vector<int> vec;void traversal(TreeNode* root) {if (root == NULL) return;traversal(root->left);vec.push_back(root->val); // 将二叉搜索树转换为有序数组traversal(root->right);}
public:bool isValidBST(TreeNode* root) {vec.clear(); // 不加这句在leetcode上也可以过,但最好加上traversal(root);for (int i = 1; i < vec.size(); i++) {// 注意要小于等于,搜索树里不能有相同元素if (vec[i] <= vec[i - 1]) return false;}return true;}

把二叉树转变为数组来判断,是最直观的,但其实不用转变成数组,可以在递归遍历的过程中直接判断是否有序。有三个陷阱需要解决
迭代法-中序遍历


16.二叉搜索树的最小绝对差

(题目链接)
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。


总结

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

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

相关文章

【LeetCode】二、链表相关:移除与反转链表

文章目录 1、链表结构2、leetcode203&#xff1a;移除链表元素3、leetcode206&#xff1a;反转链表 1、链表结构 和数组不同&#xff0c;此时不需要连续的内存空间&#xff0c;如下为单端链表&#xff0c;无pre指针 时间复杂度&#xff1a; 和数组相反&#xff0c;访问元素时…

Jackson和fastjson解决序列化时字段属性大小写改变的问题

在部分特殊场景下&#xff0c;我们可能会把实体的字段属性改成全部大写&#xff0c;但是在返回前端时&#xff0c;字段会被序列化成小写。 比如我们有一个这个类属性都是大写&#xff1a; 后端接口是这样的 然后我们请求后&#xff0c;会发现我们的字段被变成全部小写的。 …

CCAA:认证通用基础 7(认证的基本概念)

7认证的基本概念 7.1认证类型(产品认证、管理体系认证、服务认证)及基本特征 第一节 认证 1.认证的定义和本质 1.1认证的定义 (1)认证:与产品、过程、体系或人员有关的第三方证明。 ①”产品&#xff0c;过程&#xff0c;体系或人员”是认证的对象&#xff0c;认证是对“产…

软考中级:信息系统管理工程师备考资源

信息系统管理工程师备考资源 1 备考资源内容2 使用心得3 资源地址 1 备考资源内容 资源内容包含三部分&#xff1a;教程书籍pdf、备考笔记、历年真题 可以结合“软考通”APP进行练习备考&#xff0c;无偿分享。 2 使用心得 上面的资源很多&#xff0c;可以先从复习笔记开…

如何提高工业交换机的电源功耗?

工业交换机的电源功耗是指在工作状态下所消耗的能量。随着工业自动化技术的发展&#xff0c;工业交换机在生产和制造领域中扮演着至关重要的角色。它们通过连接各种设备和系统&#xff0c;实现信息的传输和处理&#xff0c;提高生产效率和质量。然而&#xff0c;工业交换机的大…

高质量3d建模素材网站推荐,建议收藏!

很多设计师、建模师想要制作出高质量的3D模型&#xff0c;除了扎实的技巧和丰富的经验外&#xff0c;还需要大量的高质量素材。那么到哪里去找高质量3d建模素材网站呢?本文将给大家推荐一些&#xff0c;建议收藏! 1、建e网&#xff1a;建e网是一个专注于为建筑、室内、景观设计…

郑州大学人工智能简答

第一章 1. 什么是人工智能&#xff1f; 人工智能又称机器智能&#xff0c;主要研究人工的方法和技术开发智能机器或智能系统&#xff0c;以模仿、延伸和扩展人的智能、生物智能、自然智能&#xff0c;实现机器的智能行为。 人工智能的定义分四类&#xff1a; &#xff08;1&am…

政务网站(.gov)应选择什么样的SSL证书

政府网站作为公共服务的重要平台&#xff0c;承载着发布政策信息、提供在线服务、促进政民互动等功能&#xff0c;其数据安全性和网站可信度尤为重要。因此&#xff0c;选择合适的SSL证书对于政府网站而言&#xff0c;不仅是遵循网络安全法规的需要&#xff0c;也是提升公众信任…

【ai】trition:tritonclient yolov4:ubuntu18.04部署python client成功

X:\05_trition_yolov4_clients\01-python server代码在115上,client本想在windows上, 【ai】trition:tritonclient.utils.shared_memory 仅支持linux 看起来要分离。 【ai】tx2 nx:ubuntu18.04 yolov4-triton-tensorrt 成功部署server 运行 client代码远程部署在ubuntu18.0…

微服务架构设计关键点总结

1.微服务架构设计通用语言 2.微服务架构组成 NFRS&#xff08;非功能性需求&#xff09;补充 3.DDD 省略 4.其他 Backend for frontend &#xff08;BFF&#xff09; pattern: 针对不同的客户端定义不同的api gateway API组合模式&#xff1a;一次性返回关联后的结果 eg:ap…

优思学院|精益生产3大特征、5个步骤、8大浪费、10大工具

前言 精益生产作为一种先进的生产管理理念&#xff0c;起源于丰田汽车公司的生产方式&#xff0c;其核心在于消除浪费、优化流程&#xff0c;以最少的投入获取最大的产出。本文将详细解析精益生产的三大特征、五个步骤、八大浪费和十大工具&#xff0c;帮助读者深入理解这一理…

威纶通模板元件功能使用,重复调用模板界面

目录 STEP 1 定义模板范围STEP 2 创建地址STEP 3 新建模板STEP 4 调用模板STEP 5 仿真测试 STEP 1 定义模板范围 选择元件-模板窗口 定义模板窗口范围 这是将窗口20-30定义为模板窗口 STEP 2 创建地址 定义几个标签地址&#xff0c;这里关联的内部地址 如果使用外部PLC地址…

【知识学习】Unity3D——Surface Shaderlightning的概念及使用方法示例

Unity3D是一个广泛使用的跨平台游戏引擎&#xff0c;它提供了强大的图形渲染功能。在Unity中&#xff0c;Shader是用于控制图形渲染过程的程序&#xff0c;它们运行在GPU上&#xff0c;用于计算屏幕上每个像素的颜色。Surface Shader和Lighting是Unity Shader编程中非常重要的概…

Apache HBase概述(图文并茂~)

HBase概述 1. Why we need HBase &#xff1f; 在大数据时代来临之前&#xff0c;我们通常依赖传统的关系型数据库&#xff08;如RDBMS&#xff09;来处理数据存储和管理。然而&#xff0c;随着数据量的急剧增长和数据结构的多样化&#xff0c;传统数据库系统开始显露出其局限性…

深入探讨极限编程(XP):技术实践与频繁发布的艺术

目录 前言1. 极限编程的核心原则1.1 沟通1.2 简单1.3 反馈1.4 勇气1.5 尊重 2. 关键实践2.1 结对编程2.1.1 提高代码质量2.1.2 促进知识共享2.1.3 增强团队协作 2.2 测试驱动开发&#xff08;TDD&#xff09;2.2.1 提升代码可靠性2.2.2 提高代码可维护性2.2.3 鼓励良好设计 2.3…

RabbitMQ实践——临时队列

临时队列是一种自动删除队列。当这个队列被创建后&#xff0c;如果没有消费者监听&#xff0c;则会一直存在&#xff0c;还可以不断向其发布消息。但是一旦的消费者开始监听&#xff0c;然后断开监听后&#xff0c;它就会被自动删除。 新建自动删除队列 我们创建一个名字叫qu…

ee trade:黄金投资是选择短线交易还是长线投资

黄金投资既可以通过短线交易获取快速收益&#xff0c;也可以采取长线投资策略获得稳健回报。本文将详细比较这两种策略的特点和适用性&#xff0c;为新手投资者提供参考。 短线交易 短线交易指在较短的时间内多次买卖以获取利润&#xff0c;通常交易周期为数日到数周。以下是…

66Uptime – 网站服务器 Cronjob 监控工具 v35.0.0扩展中文版安装

66Uptime是一款自托管、易于使用、轻量级且高性能的网站服务器和Cronjob监控工具。以其丰富的功能和便捷的管理方式&#xff0c;为用户提供了全方位的网站服务器和Cronjob监控解决方案&#xff1a; 主要功能&#xff1a; 监控网站服务器和Cronjob的运行状态&#xff0c;确保它们…

开发RpcProvider的发布服务(NotifyService)

1.发布服务过程 目前完成了mprpc框架项目中的以上的功能。 作为rpcprovider的使用者&#xff0c;也就是rpc方法的发布方 main函数如下&#xff1a; 首先我们init调用框架的init&#xff0c;然后启动一个provider&#xff0c;然后向provider上注册服务对象方法&#xff0c;即us…