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;会发现我们的字段被变成全部小写的。 …

linux服务器解压/压缩文件

在Linux服务器上&#xff0c;可以使用zip和tar命令来进行文件的打包&#xff08;压缩&#xff09;和解包&#xff08;解压缩&#xff09;。下面是它们的基本用法&#xff1a; 打包&#xff08;压缩&#xff09;与解压方法&#xff1a; 1. 使用 zip 命令 打包成 .zip 文件&am…

Java面试题:讨论如何使用JVM工具(如jconsole、jstack、jmap)诊断内存泄漏

诊断Java应用程序中的内存泄漏可以使用JVM提供的多种工具&#xff0c;如jconsole、jstack和jmap。这些工具可以帮助开发者监控和分析Java应用程序的运行状况&#xff0c;定位内存泄漏的根源。以下是这些工具的详细介绍及其使用方法&#xff1a; 1. jconsole JConsole&#xf…

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

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

PyQt6+mitmproxy,实现抓取网络请求并打印到桌面的窗口中

你可以将你的PyQt6应用程序与mitmproxy结合使用&#xff0c;以便在GUI中显示拦截的HTTP请求和响应。以下是修改后的代码&#xff1a; 安装依赖项&#xff1a; 确保你已经安装了PyQt6和mitmproxy&#xff1a; pip install PyQt6 mitmproxy编写Python代码&#xff1a; 创建一个Py…

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

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

Kotlin作用域函数it和with的使用场景

在 Kotlin 中&#xff0c;apply、run、with 使用 this&#xff0c;而 let 和 also 使用 it&#xff0c;这背后的原因是为了提供灵活性和代码清晰度。不同的作用域函数有不同的设计目的&#xff0c;选择使用 this 或 it 是为了适应不同的使用场景。以下是详细解释&#xff1a; …

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

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

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

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

郑州大学人工智能简答

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

ai语音智能电销机器人的运用有哪些,呼叫系统部署

现在智能电销机器人仍是很火&#xff0c;智能电销机器人的运用有哪些&#xff0c;到底有什么效果&#xff1f;智能电销机器人运用有哪些了&#xff0c;我们一起来看看 1、确保心情丰满。电销人员在作业中&#xff0c;会由于作业比较单调而导致心情烦躁&#xff0c;不能确保全天…

Java--乐观锁

乐观锁是一种并发控制机制&#xff0c;用于处理多个事务或线程对同一数据进行并发修改的问题。它假设多个事务或线程在操作数据时不会互相干扰&#xff0c;因此不在数据上加锁&#xff0c;而是在提交数据时检查数据是否被其他事务修改过。如果数据在提交前已经被其他事务修改&a…

政务网站(.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;帮助读者深入理解这一理…

ubuntu 18 虚拟机安装(2)

ubuntu 18 虚拟机安装&#xff08;2&#xff09; ● Ubuntu版本查看 lsb_release -a ● mysql 版本查看 mysql --version 安装 vi 安装vim&#xff1a; ubuntu预装的是vim tiny版本&#xff0c;而需要的是vim full版本。执行下面的语句安装vim full版本&#xff1a; $su…

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

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