当前位置: 首页 > 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;延迟初…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...