二叉树二叉树二叉树二叉树二叉树
目录
530.二叉搜索树的最小绝对差
需要领悟一下二叉树遍历上双指针操作,优先掌握递归
题目:
给你一个二叉搜索树的根节点 root
,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
思路:
用中序遍历生成一有序数组,遍历数组,去两数之差的最小值。
代码如下:
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;
}
};
跟昨天的最后一题类似,也可以在递归中直接进行处理,代码如下:
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;
}
};
501.二叉搜索树中的众数
和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。
题目:
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
思路:
遍历这个树,用之前学过的map统计频率,然后取频率最高的元素。
代码如下:
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;
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++) {
if (vec[i].second == vec[0].second) result.push_back(vec[i].first);
else break;
}
return result;
}
};
另一种方法是,中序遍历这个二叉树,在遍历的时候,记录之前的节点,将它与之后的节点进行比较,在比较的过程中,计它重复的次数存储在count中,与之后的节点元素若不同count为1。Count处理完毕之后,将它与最大次数maxcount进行比较,根据情况对maxcount进行一定的更新,之后继续遍历。
具体代码如下:
class Solution {
private:
int maxCount = 0; // 最大频率
int count = 0; // 统计频率
TreeNode* pre = NULL;
vector<int> result;
void searchBST(TreeNode* cur) {
if (cur == NULL) return ;
searchBST(cur->left); // 左
// 中
if (pre == NULL) { // 第一个节点
count = 1;
} else if (pre->val == cur->val) { // 与前一个节点数值相同
count++;
} else { // 与前一个节点数值不同
count = 1;
}
pre = cur; // 更新上一个节点
if (count == maxCount) { // 如果和最大值相同,放进result中
result.push_back(cur->val);
}
if (count > maxCount) { // 如果计数大于最大值频率
maxCount = count; // 更新最大频率
result.clear(); // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
result.push_back(cur->val);
}
searchBST(cur->right); // 右
return ;
}
public:
vector<int> findMode(TreeNode* root) {
count = 0;
maxCount = 0;
pre = NULL; // 记录前一个节点
result.clear();
searchBST(root);
return result;
}
};
236. 二叉树的最近公共祖先
本题其实是比较难的,可以先看我的视频讲解
题目:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
思路:
这道题采用后序遍历(左右中)进行回溯过程,根据左右子树的返回值,来处理中节点的逻辑。回溯遍历整棵二叉树,将结果返回头结点。
代码如下:
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{
return NULL;
}
}
};