当前位置: 首页 > news >正文

代码随想录算法训练营day18

代码随想录算法训练营

—day18

文章目录

  • 代码随想录算法训练营
  • 前言
  • 一、530.二叉搜索树的最小绝对差
    • 递归法
    • 迭代法
  • 二、501.二叉搜索树中的众数
    • 普通二叉树的方法
    • 递归法
    • 中序迭代法
  • 三、 236. 二叉树的最近公共祖先
    • 递归法
  • 总结


前言

今天是算法营的第18天,希望自己能够坚持下来!
今日任务:
● 530.二叉搜索树的最小绝对差
● 501. 二叉搜索树中的众数
● 236. 二叉树的最近公共祖先


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

题目链接
文章讲解
视频讲解

思路:
二叉搜索树的特点,中序遍历得出递增的数组。
因此最小绝对差就会出现在相邻的两个元素之间。
使用双指针的方法,一前一后指向树的两个节点,记录最小绝对差。

递归法

  1. 递归函数的参数和返回值:参数:当前传入节点。 返回值:用一个全局变量存储最小绝对差,所以不需要返回值。
  2. 终止条件:遇到空节点了为终止。
  3. 单层递归的逻辑:递归左节点;计算当前节点和上一个节点的差,记录最小值;递归右节点
/*** 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 result = INT_MAX;TreeNode* pre = nullptr; //指向上一个节点//使用双指针和中序遍历,计算相邻的两个节点的差,记录最小值void traversal(TreeNode* cur) {if (cur == nullptr) return;traversal(cur->left);//左if (pre != nullptr) result = min(result, cur->val - pre->val); //中pre = cur;//更新pre指针traversal(cur->right);//右return;}int getMinimumDifference(TreeNode* root) {traversal(root);return result;}
};

迭代法

使用中序迭代法模板也可以做。
代码如下:

/*** 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 getMinimumDifference(TreeNode* root) {int result = INT_MAX;TreeNode* pre = nullptr;stack<TreeNode*> st;TreeNode* cur = root;while (cur != nullptr || !st.empty()) {if (cur != nullptr) { // 指针来访问节点,访问到最底层st.push(cur); // 将访问的节点放进栈cur = cur->left; //左} else {cur = st.top();st.pop();if (pre != nullptr) { //中result = min(result, cur->val - pre->val);}pre = cur;cur = cur->right; //右}}return result;}
};

二、501.二叉搜索树中的众数

题目链接
文章讲解
视频讲解

普通二叉树的方法

思路:

  1. 遍历二叉树,将每个元素和出现的次数记录在map中
  2. 将map转成vector,定义一个cmp函数,将vector用sort按降序排序
  3. 取vector的第一个元素,然后遍历vector看是否还有出现频率相同的其他元素。

代码如下:

/*** 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 {
private:void searchBST(TreeNode* cur, unordered_map<int,int>& map) {if (cur == nullptr) return;map[cur->val]++;searchBST(cur->left, map);searchBST(cur->right, map);}//这里定义成static调用的时候就不需要对象bool static cmp (const pair<int,int>& a, const pair<int,int>& b) { return a.second > b.second;}public:vector<int> findMode(TreeNode* root) {unordered_map<int, int> map;vector<int> result;if (root == nullptr) return result;searchBST(root, map); //遍历二叉树将元素出现频率保存在map中vector<pair<int,int>> vec(map.begin(), map.end()); //将map转成vector来排序sort(vec.begin(), vec.end(), cmp); //排序,a>b返回true,a在前面,降序result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result;}
};

递归法

跟上一题计算最小绝对差一样,可以使用双指针的方法,因为是二叉搜索树,按照中序遍历,相同节点值只会是相邻的节点。

  1. 递归函数的参数和返回值:参数:当前传入节点。 返回值:用一个全局变量存储结果集,所以不需要返回值。
  2. 终止条件:遇到空节点了为终止。
  3. 单层递归的逻辑:递归左节点;
    ·用count变量统计当前遍历元素的频率,用MaxCount保存最大频率,
    ·如果当前节点是第一个节点,count=1,如果pre = cur,count++,
    ·如果pre !=cur,说明是新的元素,重新从1开始计数,count=1;
    ·并且通过比较count和MaxCount的大小,实时更新结果集,
    · 当MaxCount更新之后,需要对根据旧MaxCount保存下来的结果集清空,重新放入新的元素;
    ·递归右节点
/*** 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 MaxCount = 0; //最大频率int count = 0; //统计频率vector<int> result;TreeNode* pre = nullptr;void traversal(TreeNode* cur) {if (cur == nullptr) return;traversal(cur->left); //左//中if (pre == nullptr) count = 1; //第一个节点else if (pre->val == cur->val) count++; //上一个节点跟当前节点相同else count = 1; //上一个节点跟当前节点不相同pre = cur; //更新上一个节点if (count == MaxCount) result.push_back(cur->val); //如果和最大值相等,放入结果集if (count > MaxCount) { //当目前元素出现的次数比最大值高,清空之前的结果集,把当前元素放入结果集MaxCount = count; //更新最大频率result.clear();result.push_back(cur->val);}traversal(cur->right); //右}vector<int> findMode(TreeNode* root) {if (root == nullptr) return result;traversal(root);return result;}
};

中序迭代法

套用中序迭代法的模版,对于中间节点的处理跟递归法是一样的。代码如下:

/*** 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:vector<int> findMode(TreeNode* root) {int count = 0; //统计频率int MaxCount = 0; //最大频率vector<int> result;TreeNode* pre = nullptr;stack<TreeNode*> st;TreeNode* cur = root;//中序迭代法,向左遍历,将遍历过的元素放入栈中,直到空节点了再将栈中节点取出处理,然后向右遍历//其余思路跟递归法一样,用双指针while (cur != nullptr || !st.empty()) {if (cur != nullptr) {st.push(cur); //指针访问节点,访问到最底层cur = cur->left; //左} else {cur = st.top();st.pop();//中if (pre == nullptr) count = 1; //第一个节点else if (pre->val == cur->val) count++; //与前一个节点数值相同else count = 1; //与前一个节点数值不同pre = cur; //更新前一个节点if (count == MaxCount) result.push_back(cur->val); //如果和最大值相同,放入结果集if (count > MaxCount) { //如果计数大于最大值频率MaxCount = count; //更新最大频率result.clear(); //清空之前最大值频率存的结果集result.push_back(cur->val); //放入当前频率最大的值}cur  = cur->right; //右}}return result;}
};

三、 236. 二叉树的最近公共祖先

题目链接
文章讲解
视频讲解

情况一,如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先:
在这里插入图片描述
情况二,节点本身p(q),它拥有一个子孙节点q§:
在这里插入图片描述

思路:
需要从下往上返回结果才知道p和q的共同祖先是谁。使用后序遍历,将左节点和右节点的结果返回给中间节点。

完整过程如下:
在这里插入图片描述

递归法

  1. 递归函数的参数和返回值:传入树的根节点,递归函数的返回值为数值之和
  2. 终止条件:如果遍历到空节点,那么左叶子值一定是0;
  3. 只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。
  4. 如果当前遍历的节点是叶子节点,那其左叶子也必定是0;
  5. 单层递归的逻辑:当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public://后序递归//回溯的思想,当找到p和q的时候返回节点给上一层,此时返回的是p和q的位置//上一层同时获取到p和q的节点,那么说明当前节点就是最近公共祖先//将该节点继续返回给上层,此时返回的是公共祖先TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//当root为空返回空,找到p或者q节点向上返回if (!root || root == p || root== q) return root;TreeNode* left = lowestCommonAncestor(root->left, p, q); //向左遍历,找p或q或者公共祖先TreeNode* right = lowestCommonAncestor(root->right, p, q);//向右遍历,找p或q或者公共祖先if (left && right) return root; //p和q分别在当前节点左右侧,说明当前节点是公共祖先else if (!left && right) return right; //只在右节点发现p或者q,或者公共祖先在右节点,将结果返回上层else if (left && !right) return left; //只在左节点发现p或者q,或者公共祖先在右节点,将结果返回上层else return nullptr;}
};

总结

今天主要是学习了:
1.搜索二叉树的对相邻两个节点值的操作,可以使用双指针的方式一前一后操作。
2.通过使用一直清空和更新结果集,可以将本来需要遍历两次的功能只用一次就完成了。
3.有递归就有回溯!从下往上返回结果要用后序遍历,也就是回溯的思想。

明天继续加油!

相关文章:

代码随想录算法训练营day18

代码随想录算法训练营 —day18 文章目录 代码随想录算法训练营前言一、530.二叉搜索树的最小绝对差递归法迭代法 二、501.二叉搜索树中的众数普通二叉树的方法递归法中序迭代法 三、 236. 二叉树的最近公共祖先递归法 总结 前言 今天是算法营的第18天&#xff0c;希望自己能够…...

Kafka安全优化文档:漏洞修复到安全加固

文章目录 1.1.漏洞修复1.1.1.Apache Kafka反序列化漏洞1.1.2.pm2-kafka代码执行漏洞1.1.3.Apache Kafka安全绕过漏洞1.1.4.Apache Kafka Distribution - Schema Repository跨站请求伪造漏洞1.1.5.Apache Kafka输入验证错误漏洞的补丁1.1.6.Apache Kafka信息泄露漏洞1.1.7.Apach…...

Markdown如何添加任务列表-复选框的添加

Markdown如何添加任务列表-复选框的添加 前言语法讲解使用场景及应用实例代码整和渲染结果小结其他文章快来试试吧☺️ Markdown如何添加任务列表-复选框的添加&#x1f448;点击这里也可查看 前言 To-do任务列表是一种很常见的时间管理工具&#xff0c;它适用于工作计划&…...

基于下垂控制的构网变换器功率控制【微电网变流器】【Simulink】

目录 主要内容 理论研究 整体模型 PQ计算模块 功率控制模块 PWM反馈模块 结果一览 下载链接 主要内容 该仿真针对微电网中分布式电源接入后产生的谐波影响&#xff0c;除了污染网络外&#xff0c;还会恶化微电网变流器输出电流&#xff0c;为了消除谐波影响&a…...

AI定义汽车/跨域融合/整车智能,汽车智能化2.0时代新机会来了

汽车智能化2.0&#xff0c;产业正在发生深度变革。 一方面&#xff0c;AI大模型开始在多个域同步赋能智能汽车&#xff0c;从智能座舱到智能驾驶&#xff0c;再到底盘域&#xff0c;AI大模型正在快速推动汽车变革为超级智能体&#xff0c;AI定义汽车时代开始来临。 另一方面&…...

(leetcode算法题)10. 正则表达式匹配

10. 正则表达式匹配 - 力扣&#xff08;LeetCode&#xff09; 此题的要求一个字符串 s 和一个字符规律 p之间支持 . 和 * 的正则表达式匹配 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s 的&#xff0c;而不是部分字符串…...

SpringCloudAlibaba实战入门之Sentinel服务降级和服务熔断(十五)

一、Sentinel概述 1、Sentinel是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 一句话概括:sentinel即Hystrix的替代品,官网: https://sentinelguard.io/zh…...

使用爬虫技术获取网页中的半结构化数据

目录 前言1. 半结构化数据与爬虫技术简介1.1 半结构化数据的定义与特性1.2 爬虫技术的基本原理 2. 爬取半结构化数据的实现过程2.1 明确目标与准备2.2 发送HTTP请求2.3 解析网页内容2.4 动态内容的处理2.5 数据存储与清洗 3. 技术挑战与应对策略3.1 处理反爬机制3.2 提高爬取效…...

2025/1/1 路由期末复习作业二

呼呼呼祝大家元旦节快乐啦&#xff01;&#xff08;我顶着我超重的黑眼圈说&#xff09; 昨天一个人在寝室一边吃泡面&#xff0c;一边看步步惊心&#xff0c;一边吃一边哭呜呜呜呜呜若曦为什么不和八爷在一起好好爱&#xff0c;就因为他不当皇帝蛮&#xff01;难测最是帝王心…...

OpenCV-Python实战(13)——图像轮廓

一、找轮廓 cv2.findContours() contours,hierarchy cv2.findContours(image*,mode*,method*) contours&#xff1a;找到的所有轮廓数组&#xff0c;数组内的元素为轮廓像素点坐标。 hierarchy&#xff1a;轮廓间的层次关系。 image&#xff1a;二值图像&#xff08;cv2.t…...

javascript变量

变量 命名规范 以 字母、数字、下划线、美元符号 $ 组成、不能以 数字开头、且不能使用 js 中的关键字。 命名规范推荐采用小驼峰 命名法 。类名 采用 大驼峰命名。 var 声明变量的特点 在 script 上下文中定义的是 全局变量&#xff0c;全局变量会自动称为 window的属性。 在…...

在K8S中,如何查看kubelet组件的日志?

在kubernetes中&#xff0c;查看Kubelet组件的日志可以通过几种不同的方法。以下是详细的步骤&#xff1a; 1. 使用journalctl命令&#xff1a; 如果kubelet是通过systemd方式部署&#xff0c;你可以使用journalctl命令来查看其日志。执行journalctl -u kubelet将显示Kubelet…...

android studio android sdk下载地址

android studio安装后&#xff0c;因为公司网络原因&#xff0c;一直无法安装android sdk 后经过手机网络&#xff0c;安装android sdk成功如下&#xff0c;也可以手动下载后指定android sdk本地目录 https://dl.google.com/android/repository/source-35_r01.zip https://dl…...

Fetch处理大模型流式数据请求与解析

为什么有的大模型可以一次返回多个 data&#xff1f; Server-Sent Events (SSE)&#xff1a;允许服务器连续发送多个 data: 行&#xff0c;每个代表一个独立的数据块。 流式响应&#xff1a;大模型服务通常以流式响应方式返回数据&#xff0c;提高响应速度。 批量处理&#x…...

FPGA自学之路:到底有多崎岖?

FPGA&#xff0c;即现场可编程门阵列&#xff0c;被誉为硬件世界的“瑞士军刀”&#xff0c;其灵活性和可编程性让无数开发者为之倾倒。但谈及FPGA的学习难度&#xff0c;不少人望而却步。那么&#xff0c;FPGA自学之路到底有多崎岖呢&#xff1f; 几座大山那么高&#xff1f;…...

从0到机器视觉工程师(二):封装调用静态库和动态库

目录 静态库 编写静态库 使用静态库 方案一 方案二 动态库 编写动态库 使用动态库 方案一 方案二 方案三 总结 静态库 静态库是在编译时将库的代码合并到最终可执行程序中的库。静态库的优势是在编译时将所有代码包含在程序中&#xff0c;可以使程序独立运行&…...

[极客大挑战 2019]Knife1

这里很显然&#xff0c;根据提示可以猜测&#xff0c;已经有一句话木马上传了&#xff0c;但是路径这里不是很清楚&#xff0c;不知道路径在哪里&#xff0c;不过还是用菜刀连一下试试&#xff1a; 连接成功&#xff0c;在根目录下发现flag。不过如果不用菜刀&#xff0c;可以用…...

【在Python中生成随机字符串】

在Python中生成随机字符串&#xff0c;你可以结合使用random模块和字符串操作。以下是一个常用的方法&#xff0c;通过从预定义的字符集中随机选择字符来构建字符串&#xff1a; import random import stringdef generate_random_string(length):# 定义字符集&#xff1a;可以…...

【three.js】场景搭建

three.js由场景、相机、渲染器、灯光、控制器等几个要素组成。每个要素都有不同的类型&#xff0c;例如光照有太阳光、环境光、半球光等等。每种光照都有不同的属性可以进行配置。 场景 场景&#xff08;scene&#xff09;&#xff1a;场景是所有物体的容器&#xff0c;如果要…...

Singleton: WebRTC中ThreadManager中的单例模式

1. 什么是单例模式&#xff1a; 旨在确保一个类只有一个实例&#xff0c;并提供全局访问点。 应用场景&#xff1a;需要一个全局唯一的实例&#xff0c;避免资源浪费。 2. 单例模式的实现&#xff1a; Lazy Initialization&#xff08;懒汉式&#xff09;&#xff08;延迟初…...

U-boot QSPI驱动移植实战:从Flash适配到启动验证全解析

1. 项目概述&#xff1a;为什么U-boot的QSPI驱动移植是个“硬骨头”&#xff1f;在嵌入式系统开发&#xff0c;尤其是基于ARM Cortex-A系列处理器的工控、车载或高端物联网设备中&#xff0c;U-boot作为系统启动的“第一棒”至关重要。而QSPI&#xff08;Quad SPI&#xff09;接…...

DDrawCompat:如何在现代Windows上为经典DirectX游戏注入新生命?

DDrawCompat&#xff1a;如何在现代Windows上为经典DirectX游戏注入新生命&#xff1f; 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/…...

wBlock Safari扩展架构详解:5个内容拦截扩展的协同工作原理

wBlock Safari扩展架构详解&#xff1a;5个内容拦截扩展的协同工作原理 【免费下载链接】wBlock The next-generation ad blocker for Safari. 项目地址: https://gitcode.com/gh_mirrors/wb/wBlock wBlock是一款下一代Safari广告拦截器&#xff0c;通过创新的多扩展架构…...

在Windows 11 LTSC版本中找回微软商店的3分钟魔法

在Windows 11 LTSC版本中找回微软商店的3分钟魔法 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 你是否正在使用Windows 11 24H2 LTSC版本&#xff0…...

独立开发者如何利用 Taotoken 统一管理多个 AI 项目支出

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 独立开发者如何利用 Taotoken 统一管理多个 AI 项目支出 对于同时维护多个小型 AI 应用或实验项目的独立开发者而言&#xff0c;成…...

超越基础扫描:实战解析Tessent ATPG中的Clock PO与RAM Sequential Patterns如何提升故障覆盖率

超越基础扫描&#xff1a;实战解析Tessent ATPG中的Clock PO与RAM Sequential Patterns如何提升故障覆盖率 在数字电路测试领域&#xff0c;达到95%以上的故障覆盖率曾是许多DFT工程师的终极目标&#xff0c;直到他们遇到了时钟驱动输出和嵌入式RAM模块。这些特殊结构如同电路…...

Power BI主题模板完全指南:35+ JSON模板快速构建专业数据可视化方案

Power BI主题模板完全指南&#xff1a;35 JSON模板快速构建专业数据可视化方案 【免费下载链接】PowerBI-ThemeTemplates Snippets for assembling Power BI Themes 项目地址: https://gitcode.com/gh_mirrors/po/PowerBI-ThemeTemplates 在数据驱动的商业决策时代&…...

终极IDM激活脚本完全指南:三步实现永久免费下载神器

终极IDM激活脚本完全指南&#xff1a;三步实现永久免费下载神器 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script 还在为IDM的30天试用期烦恼吗&#xff1f;IDM Ac…...

实战配置:5个提升MPC-HC播放器性能的专业技巧

实战配置&#xff1a;5个提升MPC-HC播放器性能的专业技巧 【免费下载链接】mpc-hc MPC-HCs main repository. For support use our Trac: https://trac.mpc-hc.org/ 项目地址: https://gitcode.com/gh_mirrors/mpc/mpc-hc Media Player Classic - Home Cinema&#xff0…...

新手开发者首次使用 Taotoken 从注册到完成第一个 API 调用的全过程体验

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 新手开发者首次使用 Taotoken 从注册到完成第一个 API 调用的全过程体验 作为一名刚开始接触大模型应用开发的程序员&#xff0c;我…...