代码随想录1016-Day16

embedded/2024/11/25 17:42:40/

目录

  • 530.二叉搜索树的最小绝对差
  • 501.二叉搜索树中的众数
  • 105.从中序与前序遍历序列构造二叉树
    • 总结
  • 收获

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

文章链接:代码随想录
题目链接:题目

思路:用中序遍历遍历一遍 BST 的所有节点得到有序结果,然后在遍历过程中计算最小差值即可
需要用一个pre节点记录一下cur节点的前一个节点:在递归中记录前一个节点的指针

    
/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int res = INT_MAX;TreeNode * prev = nullptr;int getMinimumDifference(TreeNode* root) {traverse(root);return res;}void traverse(TreeNode* root){if(!root) return;traverse(root->left);if(prev){res = min(res, abs(root->val - prev->val));}prev = root;traverse(root->right);}
};

501.二叉搜索树中的众数

文章链接:代码随想录
题目链接:题目

思路:
这道题需要用到「遍历」的思维。

BST 的中序遍历有序,在中序遍历的位置做一些判断逻辑和操作有序数组差不多,很容易找出众数。
注意:
频率count 大于 maxCount的时候,不仅要更新maxCount,而且要清空结果集(以下代码为result数组),因为结果集之前的元素都失效了

class Solution {
private:int maxCount = 0; // 最大频率int count = 0; // 统计频率TreeNode* pre = NULL;vector<int> result;void searchBST(TreeNode* cur) {if (cur == NULL) return ;searchBST(cur->left);       // 左// 中if (pre == NULL) { // 第一个节点count = 1;} else if (pre->val == cur->val) { // 与前一个节点数值相同count++;} else { // 与前一个节点数值不同count = 1;}pre = cur; // 更新上一个节点if (count == maxCount) { // 如果和最大值相同,放进result中result.push_back(cur->val);}if (count > maxCount) { // 如果计数大于最大值频率maxCount = count;   // 更新最大频率result.clear();     // 很关键的一步,不要忘记清空result,之前result里的元素都失效了result.push_back(cur->val);}searchBST(cur->right);      // 右return ;}public:vector<int> findMode(TreeNode* root) {count = 0;maxCount = 0;pre = NULL; // 记录前一个节点result.clear();searchBST(root);return result;}
};

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

文章链接:代码随想录
题目链接:题目

思路:
构造二叉树,第一件事一定是找根节点,然后想办法构造左右子树。
在这里插入图片描述

二叉树的前序和中序遍历结果的特点如下:

在这里插入图片描述

前序遍历结果第一个就是根节点的值,然后再根据中序遍历结果确定左右子树的节点。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:unordered_map<int, int> hash;TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {for (int i = 0; i < inorder.size(); i++){hash[inorder[i]] = i;}return buildTree(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1);}TreeNode* buildTree(vector<int>&preorder,int pl, int pr, vector<int>& inorder, int il, int ir){if(pl > pr) return nullptr;auto val = preorder[pl];//根据前序遍历的值 从哈希表中找到对应中序遍历的下标int k = hash[val];int lLength = k - il;TreeNode* root = new TreeNode(val);//pl + lLength有点没懂 //k - 1 - il// pl + 1 + k - 1 - il =>pl + k - il => pl + kroot->left = buildTree(preorder, pl + 1, pl + lLength, inorder, il, k - 1);root->right = buildTree(preorder, pl + lLength + 1, pr, inorder, k + 1, ir);return root;}
};

总结

二叉树解题的思维模式分两类:

1、是否可以通过遍历一遍二叉树得到答案?如果可以,用一个 traverse 函数配合外部变量来实现,这叫「遍历」的思维模式。

2、是否可以定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案?如果可以,写出这个递归函数的定义,并充分利用这个函数的返回值,这叫「分解问题」的思维模式。

无论使用哪种思维模式,你都需要思考:

如果单独抽出一个二叉树节点,它需要做什么事情?需要在什么时候(前/中/后序位置)做?其他的节点不用你操心,递归函数会帮你在所有节点上执行相同的操作。

收获

补之前的卡


http://www.ppmy.cn/embedded/140440.html

相关文章

STM32的中断(什么是外部中断和其他中断以及中断号是什么)

一、什么是EXTI 和NVIC EXTI&#xff08;External Interrupt/Event Controller&#xff09;EXTI 是外部中断/事件控制器&#xff0c;它负责处理外部信号变化&#xff0c;并将信号传递给中断控制器&#xff08;如 NVIC&#xff09;。主要负责以下功能&#xff1a; 外部事件检测…

[UE5学习] 一、使用源代码安装UE5.4

一、简介 本文介绍了如何使用源代码安装编译UE5.4&#xff0c;并且新建简单的项目&#xff0c;打包成安卓平台下的apk安装包。 二、使用源代码安装UE5.4 注意事项&#xff1a; 请保证可以全程流畅地科学上网。请保证C盘具有充足的空间。请保证接下来安装下载的visual studi…

golang学习-切片

切片并不是数组或数组指针&#xff0c;它通过内部指针和相关属性引用数组片段&#xff0c;以实现变长方案。“ slice 并不是真正意义上的动态数组&#xff0c;而是一个引用类型。slice 总是指向一个底层 array&#xff0c;slice 的声明也可以像array 一样&#xff0c;只是不需要…

C++结构型设计模式之使用抽象工厂来创建和配置桥接模式的例子

下面是一个使用抽象工厂模式来创建和配置桥接模式的示例&#xff0c;场景是创建不同操作系统的窗口&#xff08;Window&#xff09;及其对应的实现&#xff08;WindowImpl&#xff09;。我们将通过抽象工厂来创建不同操作系统下的窗口和实现。 代码示例 #include <iostrea…

第十章 JavaScript的应用

第十章JavaScript的应用 10.1 JavaScript概述 10.1.1 JavaScript简介 10.1.1.1 简单性 JavaScript 的语法相对简单&#xff0c;易于学习和使用。它不需要复杂的编译过程&#xff0c;开发者可以直接在浏览器中编写和调试代码。例如&#xff0c;变量声明可以不指定类型&#xff…

Go与黑客(第一部分)

本篇内容是根据2021年5月份#205 Hacking with Go音频录制内容的整理与翻译 Natalie 和 Mat 从 2 位安全研究人员的角度探讨了 Go 中的黑客行为。 Joakim Kennedy 和 JAGS 都使用 Go 进行黑客攻击&#xff1a;编写恶意软件、硬件黑客、逆向工程 Go 代码等等。 过程中为符合中文…

Spring Boot应用开发实战:构建RESTful API服务

Spring Boot应用开发实战&#xff1a;构建RESTful API服务 在当今快速迭代的软件开发环境中&#xff0c;Spring Boot凭借其“约定优于配置”的理念&#xff0c;以及丰富的生态系统&#xff0c;成为了构建现代微服务架构的首选框架之一。本文将带您深入Spring Boot的世界&…

udp_socket

文章目录 UDP服务器封装系统调用socketbind系统调用bzero结构体清0sin_family端口号ip地址inet_addrrecvfromsendto 新指令 netstat -naup (-nlup)包装器 的两种类型重命名方式包装器使用统一可调用类型 关键字 typedef 类型重命名系统调用popen关于inet_ntoa UDP服务器封装 系…