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
思路:
要解决这个问题,我们可以利用二叉搜索树(BST)的性质。
BST 中的节点值是有序的(中序遍历结果是升序的),这使得我们可以通过中序遍历来找到最小差值。
-
中序遍历 BST:在中序遍历过程中,我们将访问树中的节点值并将其存储在一个数组中。由于 BST 的中序遍历是有序的,数组中的值也会是升序的。
-
计算最小差值:一旦我们有了升序的节点值数组,我们只需要遍历数组,并计算相邻元素之间的差值,找到最小差值即可。
上代码:
/**
* 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) {
// 用于存储中序遍历结果
vector<int> inorderValues;
// 执行中序遍历
inorderTraversal(root, inorderValues);
// 初始化最小差值为最大整数
int minDiff = INT_MAX;
// 遍历中序遍历结果数组,计算相邻元素的差值
for (int i = 1; i < inorderValues.size(); ++i) {
minDiff = min(minDiff, inorderValues[i] - inorderValues[i - 1]);
}
return minDiff;
}
private:
// 中序遍历并将节点值存入数组
void inorderTraversal(TreeNode* node, vector<int>& values) {
if (node == nullptr) return;
inorderTraversal(node->left, values);
values.push_back(node->val);
inorderTraversal(node->right, values);
}
};
501.二叉搜索树中的众数
题目:
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2] 输出:[2]
示例 2:
输入:root = [0] 输出:[0]
提示:
- 树中节点的数目在范围
[1, 104]
内 -105 <= Node.val <= 105
思路:
要找出二叉搜索树中的所有众数,可以使用中序遍历(in-order traversal)来实现。
中序遍历可以帮助我们按升序访问树的所有节点值。
通过中序遍历,我们可以遍历所有节点并统计每个值的出现频率,然后找到出现频率最高的值作为众数。
-
中序遍历:首先执行中序遍历,将所有节点的值存储在一个数组或列表中。
-
统计频率:遍历存储的节点值数组,统计每个值的出现频率。
-
找出众数:遍历统计频率,找到出现频率最高的值,并返回这些值作为结果。
上代码:
/**
* 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) {
vector<int> values;
inorderTraversal(root, values);
unordered_map<int, int> frequency;
int maxCount = 0;
for (int value : values) {
frequency[value]++;
maxCount = max(maxCount, frequency[value]);
}
vector<int> modes;
for (auto& pair : frequency) {
if (pair.second == maxCount) {
modes.push_back(pair.first);
}
}
return modes;
}
private:
void inorderTraversal(TreeNode* node, vector<int>& values) {
if (!node) return;
inorderTraversal(node->left, values);
values.push_back(node->val);
inorderTraversal(node->right, values);
}
};
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
均存在于给定的二叉树中。
思路:
找出二叉树中两个节点的最近公共祖先,可以使用递归的方法来实现。
对于每个节点,判断其左子树和右子树中是否包含指定的两个节点(p
和 q
)。
如果当前节点是 p
或 q
,那么当前节点就是它们的最近公共祖先(如果另一个节点也在它的子树中)。
如果在当前节点的左子树中找到 p
和 q
,而在右子树中也找到 p
和 q
,那么当前节点就是它们的最近公共祖先。
如果只在左子树中找到 p
和 q
,或者只在右子树中找到它们,当前节点的最近公共祖先就是在那个子树中的最近公共祖先。
-
递归终止条件:
- 如果当前节点为空,则返回
nullptr
。 - 如果当前节点等于
p
或q
,则返回当前节点。
- 如果当前节点为空,则返回
上代码:
/**
* 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:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 如果当前节点为空,返回空指针
if (root == nullptr) return nullptr;
// 如果当前节点等于 p 或 q,返回当前节点
if (root == p || root == q) return root;
// 在左子树中递归查找
TreeNode* left = lowestCommonAncestor(root->left, p, q);
// 在右子树中递归查找
TreeNode* right = lowestCommonAncestor(root->right, p, q);
// 如果左子树和右子树中都找到了 p 或 q,当前节点是最近公共祖先
if (left && right) return root;
// 如果左子树中找到了 p 或 q,返回左子树的结果
if (left) return left;
// 如果右子树中找到了 p 或 q,返回右子树的结果
return right;
}
};