530.二叉搜索树的最小绝对差 ,501.二叉搜索树中的众数 ,236. 二叉树的最近公共祖先

简介: 本内容涵盖了三道二叉树相关的问题及其解法,涉及二叉搜索树的最小绝对差、二叉搜索树中的众数以及二叉树的最近公共祖先。通过中序遍历将二叉搜索树转化为有序数组以求最小差值;利用哈希表统计节点值频率并排序找出众数;通过递归方法寻找二叉树中两节点的最近公共祖先。这些题目展示了二叉树遍历、递归及数据结构应用的核心思想,是深入理解二叉树算法的重要实践。

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

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:

输入:root = [4,2,6,1,3]

输出:1

示例 2:

输入:root = [1,0,48,null,null,12,49]

输出:1

提示:

树中节点的数目范围是 [2, 104]

0 <= Node.val <= 105

思考历程与知识点:  

那么二叉搜索树采用中序遍历,其实就是一个有序数组。

在一个有序数组上求两个数最小差值,这是不是就是一道送分题了。

最直观的想法,就是把二叉搜索树转换成有序数组,然后遍历一遍数组,就统计出来最小差值了。

题解:

class Solution {
private:
vector<int> vec;
void traversal(TreeNode* root) {
    if (root == NULL) return;
    traversal(root->left);
    vec.push_back(root->val); // 将二叉搜索树转换为有序数组
    traversal(root->right);
}
public:
    int getMinimumDifference(TreeNode* root) {
        vec.clear();
        traversal(root);
        if (vec.size() < 2) return 0;
        int result = INT_MAX;
        for (int i = 1; i < vec.size(); i++) { // 统计有序数组的最小差值
            result = min(result, vec[i] - vec[i-1]);
        }
        return result;
    }
};

题目:501. 二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

结点左子树中所含节点的值 小于等于 当前节点的值

结点右子树中所含节点的值 大于等于 当前节点的值

左子树和右子树都是二叉搜索树

示例 1:

输入:root = [1,null,2,2]

输出:[2]

示例 2:

输入:root = [0]

输出:[0]

提示:

树中节点的数目在范围 [1, 104] 内

-105 <= Node.val <= 105

思考历程与知识点:  

这个树都遍历了,用map统计频率

至于用前中后序哪种遍历也不重要,因为就是要全遍历一遍,怎么个遍历法都行,层序遍历都没毛病!

把统计的出来的出现频率(即map中的value)排个序

有的同学可能可以想直接对map中的value排序,还真做不到,C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序。

所以要把map转化数组即vector,再进行排序,当然vector里面放的也是pair<int, int>类型的数据,第一个int为元素,第二个int为出现频率

取前面高频的元素

此时数组vector中已经是存放着按照频率排好序的pair,那么把前面高频的元素取出来就可以了。

题解:

class Solution {
private:
 
void searchBST(TreeNode* cur, unordered_map<int, int>& map) { // 前序遍历
    if (cur == NULL) return ;
    map[cur->val]++; // 统计元素频率
    searchBST(cur->left, map);
    searchBST(cur->right, map);
    return ;
}
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; // key:元素,value:出现频率
        vector<int> result;
        if (root == NULL) return result;
        searchBST(root, map);
        vector<pair<int, int>> vec(map.begin(), map.end());
        sort(vec.begin(), vec.end(), cmp); // 给频率排个序
        result.push_back(vec[0].first);
        for (int i = 1; i < vec.size(); i++) {
            // 取最高的放到result数组中
            if (vec[i].second == vec[0].second) result.push_back(vec[i].first);
            else break;
        }
        return result;
    }
};

题目:236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1

输出:3

解释:节点  

5  

和节点  

1  

的最近公共祖先是节点  

3 。

示例 2:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4

输出:5

解释:节点  

5  

和节点  

4  

的最近公共祖先是节点  

5 。

因为根据定义最近公共祖先节点可以为节点本身。

示例 3:

输入:root = [1,2], p = 1, q = 2

输出:1

提示:

树中节点数目在范围 [2, 105] 内。

-109 <= Node.val <= 109

所有 Node.val 互不相同 。

p != q

p 和 q 均存在于给定的二叉树中。

思考历程与知识点:  

在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。

题解:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == q || root == p || root == NULL) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if (left != NULL && right != NULL) return root;
 
        if (left == NULL && right != NULL) return right;
        else if (left != NULL && right == NULL) return left;
        else  { //  (left == NULL && right == NULL)
            return NULL;
        }
 
    }
};


相关文章
|
6月前
|
C++
20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值
本内容涵盖三道编程题的题目与题解,包括“有效的括号”(使用栈判断括号是否匹配)、“删除字符串中的所有相邻重复项”(利用栈删除相邻重复字符)以及“逆波兰表达式求值”(通过栈计算后缀表达式的结果)。每道题均采用C++实现,详细展示了栈在解决匹配问题、字符串处理和表达式求值中的应用。代码逻辑清晰,适合学习栈数据结构的应用场景与实现方法。
|
数据采集 安全 网络协议
DDoS 攻防之 HTTP Flood|学习笔记
快速学习 DDoS 攻防之 HTTP Flood
1618 0
DDoS 攻防之 HTTP Flood|学习笔记
|
6月前
|
算法
77. 组合
回溯法是一种通过递归搜索解决问题的算法,适用于组合、切割、子集、排列和棋盘等问题。以“77. 组合”为例,给定整数n和k,需找出[1, n]中所有可能的k个数的组合。此问题可抽象为树形结构,n为树宽,k为树深。通过递归与回溯,每次从集合中选取元素并调整范围,当路径长度等于k时收集结果。题解中使用`backtracking`函数实现递归,利用`path`记录当前组合,最终返回所有符合条件的结果。
|
存储 编解码 iOS开发
视频文件格式:MOV与MP4格式的区别是什么?
视频文件有多种格式,很多人在下载时不知道该选择哪种文件格式。不同格式有不同特点,各自有优缺点。本文将详细介绍常见的MOV和MP4的特点与区别,以供读者了解及选择。
8740 2
视频文件格式:MOV与MP4格式的区别是什么?
|
6月前
|
机器学习/深度学习 人工智能 PyTorch
200行python代码实现从Bigram模型到LLM
本文从零基础出发,逐步实现了一个类似GPT的Transformer模型。首先通过Bigram模型生成诗词,接着加入Positional Encoding实现位置信息编码,再引入Single Head Self-Attention机制计算token间的关系,并扩展到Multi-Head Self-Attention以增强表现力。随后添加FeedForward、Block结构、残差连接(Residual Connection)、投影(Projection)、层归一化(Layer Normalization)及Dropout等组件,最终调整超参数完成一个6层、6头、384维度的“0.0155B”模型
368 11
200行python代码实现从Bigram模型到LLM
|
6月前
|
SQL 存储 缓存
Fluss 实战:用 Partial Update 构建实时宽表的新范式
传统流式数据管道通过多表 Join 构建宽表,如实时推荐引擎需整合用户偏好、购买记录等8个数据源,但此方法在大规模场景下状态管理复杂、资源消耗高且调试困难。Fluss 提出部分更新方案,基于主键将各数据源独立写入共享宽表,避免复杂 Join 操作。示例中,通过 Flink SQL 创建推荐、曝光、点击等表,并逐步插入数据实现宽表构建。最终,借助 Fluss 的高效合并机制,输出包含最新信息的统一视图,提升可扩展性和维护性。
352 8
Fluss 实战:用 Partial Update 构建实时宽表的新范式
|
6月前
|
安全 数据可视化 Linux
在线游戏的地基:VPS和专用服务器性价比大比拼!
游戏服务器是在线游戏的基石,选择合适的服务器类型对玩家体验至关重要。本文对比了VPS(虚拟专用服务器)和专用服务器的优劣势:VPS经济灵活、易于管理,但性能和安全存在局限,适合预算有限或玩家规模适中的游戏;专用服务器性能强大、安全可靠且可控性高,但成本和技术门槛较高,更适合大型MMO或竞技游戏。根据游戏类型、预算、技术能力和扩展需求,合理选择服务器类型是关键。初创阶段可选用中端VPS,成长阶段考虑高端VPS或低端专用服务器,成熟阶段则需高端专用服务器集群。未来,混合架构或将实现性能与成本的平衡。最终,以玩家流畅体验为导向,选择最适合的服务器方案。
224 3
|
5月前
|
Web App开发 安全 测试技术
Playwright-MCP浏览器会话复用全解析
本文深入解析Playwright-MCP实现浏览器会话复用的核心技术,包括状态持久化(cookies/localStorage存储)和直接连接已打开浏览器实例(通过CDP协议)。通过多上下文隔离与安全机制设计,提供企业级应用场景的优化方案,帮助开发者提升测试效率并降低资源消耗。
|
6月前
|
存储 缓存 数据挖掘
阿里云服务器实例选购指南:经济型、通用算力型、计算型、通用型、内存型性能与适用场景解析
当我们在通过阿里云的活动页面挑选云服务器时,相同配置的云服务器通常会有多种不同的实例供我们选择,并且它们之间的价格差异较为明显。这是因为不同实例规格所采用的处理器存在差异,其底层架构也各不相同,比如常见的X86计算架构和Arm计算架构。正因如此,不同实例的云服务器在性能表现以及适用场景方面都各有特点。为了帮助大家在众多实例中做出更合适的选择,本文将针对阿里云服务器的经济型、通用算力型、计算型、通用型和内存型实例,介绍它们的性能特性以及对应的使用场景,以供大家参考和选择。
|
6月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
196 0