530.二叉搜索树的最小绝对差
题目链接:二叉搜索树的最小绝对差
题目描述:给你一个二叉搜索树的根节点
root
,返回 树中任意两不同节点值之间的最小差值 。差值是一个正数,其数值等于两值之差的绝对值。
解题思想:
这道题主要利用了二叉搜索树的中序遍历是一个有序序列,这个题就变为了一个求有序序列的最小绝对差问题。
递归法:
主要使用了双指针
class Solution {
public:
int getMinimumDifference(TreeNode* root) {
traversal(root);
return MinDiff;
}
private:
TreeNode* pre;
int MinDiff = INT32_MAX;
void traversal(TreeNode* cur) {
if (cur == NULL)
return;
traversal(cur->left);
if (pre != NULL) {
int diff = cur->val - pre->val;
if (diff < MinDiff)
MinDiff = diff;
}
pre = cur;
traversal(cur->right);
}
};
迭代法:
主要利用迭代法中序遍历模版,加上双指针。
class Solution {
public:
int getMinimumDifference(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = NULL;
int MinDiff = INT32_MAX;
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->left;
} else {
cur = st.top();
st.pop();
if (pre != NULL) {
int diff = cur->val - pre->val;
MinDiff = min(MinDiff, diff);
}
pre = cur;
cur = cur->right;
}
}
return MinDiff;
}
};
501.二叉搜索树中的众数
题目链接:二叉搜索树中的众数
题目描述:给你一个含重复值的二叉搜索树(BST)的根节点
root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
递归法:
当作普通二叉树来处理:
-
这个树都遍历了,用map统计频率
-
把统计的出来的出现频率(即map中的value)排个序
有的同学可能可以想直接对map中的value排序,还真做不到,C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序。
-
取前面高频的元素
class Solution {
public:
vector<int> findMode(TreeNode* root) {
vector<int> result;
unordered_map<int, int> map;
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;
}
private:
void searchBST(TreeNode* node, unordered_map<int, int> &map) {
if (node == NULL) {
return;
}
searchBST(node->left, map);
map[node->val]++;
searchBST(node->right, map);
}
bool static cmp(const pair<int, int>& a, const pair<int, int>& b) {
return a.second > b.second;
}
};
利用搜索二叉树的性质:中序遍布为单调递增序列。
!https://code-thinking-1253855093.file.myqcloud.com/pics/20210204152758889.png
遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。这里我们依然利用双指针的方法,分别指向cur和pre。
class Solution {
public:
vector<int> findMode(TreeNode* root) {
searchBST(root);
return result;
}
private:
TreeNode* pre = NULL;
int count = 0;
int maxCount = 0;
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.push_back(cur->val);
}
if (count > maxCount) {
maxCount = count;
result.clear();
result.push_back(cur->val);
}
searchBST(cur->right);
}
};
迭代法:
只要把中序遍历转成迭代,中间节点的处理逻辑完全一样
class Solution {
public:
vector<int> findMode(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = NULL;
int count = 1, maxCount = 0;
vector<int> result;
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->left;
} else {
cur = st.top();
st.pop();
if (pre == NULL)
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. 二叉树的最近公共祖先
题目链接:二叉树的最近公共祖先
题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
解题思路:
后序遍历,通过左右子树是否包含p和q的公共祖先来将公共祖先向上传递。
那么我给大家归纳如下三点:
- 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从底向上的遍历方式。
- 在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
- 要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return traversal(root, p, q);
}
TreeNode* traversal(TreeNode* node, TreeNode* p, TreeNode* q) {
if (node == NULL)
return NULL;
if (node == p || node == q)
return node;
TreeNode* left = traversal(node->left, p, q);
TreeNode* right = traversal(node->right, p, q);
TreeNode* result;
if (left != NULL && right != NULL)
result = node;
else if (left != NULL && right == NULL)
result = left;
else if (left == NULL && right != NULL)
result = right;
else
result = NULL;
return result;
}
};