530二叉搜索树的绝对值
题目描述:
给你一个二叉搜索树的根节点 root
,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [4,2,6,1,3] 输出:1
示例 2:
输入:root = [1,0,48,null,null,12,49] 输出:1
/*二叉搜索树的特点就是,中序遍历的时候是一个有序数组*/
class Solution {
private:
int result = INT_MAX;
TreeNode* pre = NULL;
void traversal(TreeNode* cur) {
if (cur == NULL) return;
traversal(cur->left); // 左
if (pre != NULL){ // 中
result = min(result, cur->val - pre->val);
}
pre = cur; // 记录前一个
traversal(cur->right); // 右
}
public:
int getMinimumDifference(TreeNode* root) {
traversal(root);
return result;
}
};
自己没好好读题,写了一个相邻最小差的:
代码:
class Solution {
public:
int minn=INT_MAX;
void findfuck(TreeNode* root){
if(root->left==NULL&&root->right==NULL)return ;
if(root->left){getMinimumDifference(root->left);minn=min(minn,abs((root->val)-(root->left->val)));}
if(root->right){getMinimumDifference(root->right);minn=min(minn,abs((root->val)-(root->right->val)));}
}
int getMinimumDifference(TreeNode* root) {
findfuck(root);
return minn;
}
};
501二叉搜索树的众数
题目描述:
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2] 输出:[2]
示例 2:
输入:root = [0] 输出:[0]
这个就用map来写,可以看之前的博客有对map的讲解
map<key,value>key是对应的值,value是这个值的价值(个数)
class Solution {
public:
map<int,int> map;
void searchBST(TreeNode* root){
if(root==NULL)return;
map[root->val]++;
searchBST(root->left);
searchBST(root->right);
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {
return a.second > b.second;
}
vector<int> findMode(TreeNode* root) {
vector<int> result;
if (root == NULL) return result;
searchBST(root);
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;
}
};
问题:
vector<pair<int, int>> vec(map.begin(), map.end());为什么这个vector是pair类型的,却可以放map类型的,为什么不定义为map类型的?
背景知识
-
map
的结构:map
是一个存储键值对的容器,其中每个元素都是一个pair
类型的对象,包含一个键(key)和一个值(value)。在map<int, int>
中,每个元素实际上是pair<int, int>
类型。- 例如,
map[5] = 10;
表示键为 5,值为 10 的一个pair
。
-
vector
的结构:vector
是一个动态数组,能够存储多个元素,可以是任意类型,包括用户定义的类型。vector<pair<int, int>>
表示该vector
中的每个元素都是pair<int, int>
类型。
代码解释
在这一行 vector<pair<int, int>> vec(map.begin(), map.end());
中:
map.begin()
和map.end()
返回分别指向map
开头和末尾的迭代器。- 当创建
vector<pair<int, int>>
时,使用的是map
的迭代器初始化列表。这顺序地遍历map
中的每个元素(即每个pair<int, int>
),并将它们添加到vector
中。
为什么使用 vector<pair<int, int>>
使用 vector<pair<int, int>>
而不是 map
类型有以下原因:
-
默认操作:
map
设计用于快速查找,具有按键索引的特点,而vector
是顺序容器,适合存储和操作一组数据。- 将
map
的内容放入vector
中,可以对其进行灵活的排序和遍历操作。
-
排序:
vector
允许你方便地对元素进行排序(使用sort()
函数)。map
自身是有序的,但是它不支持直接访问索引,比如要取第 n 个元素,必须通过迭代器遍历。- 在这段代码中,后面对
vec
进行了排序,以便于找到出现频率最高的元素。
-
简化处理:
- 特定情况下,将键值对放入一个
vector
中可以更简化处理业务逻辑,例如找出最大频率的元素。
- 特定情况下,将键值对放入一个
总结
vector<pair<int, int>>
用于存储来自 map
的所有键值对,以便进行排序和筛选操作。虽然直接使用 map
也是可以的,但这将使得后续操作变得繁琐(如排序和遍历)。因此,使用一个包含 pair
的 vector
在这个上下文中是更加简便和有效的选择。
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
代码:
class Solution {
public:
// 定义一个函数,接收根节点 root 和两待查节点 p 和 q
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 如果当前节点为空,返回空节点
if(root == NULL) return root;
// 如果当前节点是 p 或 q,返回当前节点
if(root == p || root == q) return root;
// 递归查找左子树中 p 和 q 的最近公共祖先
TreeNode* left = lowestCommonAncestor(root->left, p, q);
// 递归查找右子树中 p 和 q 的最近公共祖先
TreeNode* right = lowestCommonAncestor(root->right, p, q);
// 如果左子树和右子树都找到了 p 或 q,则当前节点是最近公共祖先
if(left != NULL && right != NULL) return root;
// 如果左子树为空,返回右子树的结果(可能为 NULL 或找到的节点)
if(left == NULL && right != NULL) return right;
// 如果右子树为空,返回左子树的结果(可能为 NULL 或找到的节点)
else if(left != NULL && right == NULL) {
return left;
}
// 如果左右子树均为空,返回 NULL
else {
return NULL;
}
}
};
程序分析:
-
基本条件:
- 当
root
是NULL
时,返回NULL
,这意味着树的某个部分已经被遍历到没有节点了。 - 当
root
是p
或q
时,返回当前节点,这表明找到了其中一个目标节点。
- 当
-
递归遍历:
- 函数分别在左子树和右子树中查找
p
和q
,将结果存储在left
和right
中。
- 函数分别在左子树和右子树中查找
-
确定公共祖先:
- 如果
left
和right
都非空,则说明p
和q
分别在当前节点的左侧和右侧,因此当前节点 (root
) 是它们的最近公共祖先。 - 如果只有一个子树找到了目标节点(即
left
或right
中有一个非 NULL),则返回那个子树的结果,表明在那一边找到了目标节点;如果都没有找到,则返回NULL
。
- 如果