1.二叉搜索树的最小绝对值
530. 二叉搜索树的最小绝对差
首先对于单个节点而言,其最小绝对值有两个可能
一是根节点和左节点的最右节点绝对值
二是根节点和右节点的最左节点绝对值
其实这俩条件的实现就是我们代码的关键,不过这题和二叉搜索树的判断殊途同归,其实都是分别访问了左右节点的最右最左节点。那么写起来就简单了,无非要更新一下最小值。
class Solution {
public:
void _getMiniR(TreeNode* root,int& min)
{
if(root==nullptr)
return;
int tmp;
if(root->left)
{
TreeNode* left = root->left;
while(left)
{
tmp = abs(left->val-root->val);
if(tmp<min)
min = tmp;
left=left->right;
}
}
if(root->right)
{
TreeNode* right = root->right;
while(right)
{
tmp = abs(right->val-root->val);
if(tmp<min)
min = tmp;
right=right->left;
}
}
_getMiniR(root->left,min);
_getMiniR(root->right,min);
}
int getMinimumDifference(TreeNode* root) {
int min = 100000;
_getMiniR(root,min);
return min;
}
};
2.二叉搜索树的众数
501. 二叉搜索树中的众数
我们知道哈希表的map能够统计次数,所以递归+map应该就能实现对二叉搜索树的查找
1.在外面定义一个map,引用传入递归函数,将根节点的数统计到map中,随后左右递归
2.我们先要知道哪个数是最大的,所以先要有一个变量来存储遍历map后出现次数的最大值,当然此时我们要比较的是maxnum和map元素的second。
3.找到对应的maxnum后,我们再次遍历,将second和maxnum一样的元素,其对应的first传入到vector中
lass Solution {
public:
void _findModeR(TreeNode* root,unordered_map<int,int>& um)
{
if(root==nullptr)
return;
um[root->val]++;
_findModeR(root->left,um);
_findModeR(root->right,um);
}
vector<int> findMode(TreeNode* root) {
vector<int> ret;
int num;
unordered_map<int,int> um;
_findModeR(root,um);
int maxnum = 0;
for(auto& e:um)
{
if(e.second>maxnum)
maxnum=e.second;
}
for(auto& e:um)
{
if(e.second==maxnum)
ret.push_back(e.first);
}
return ret;
}
};
但是这样没有什么针对性,因为按照这个函数,所有二叉树都能通过这个函数实现。而我们要知道的是二叉搜索树的中序遍历,得到的结果其实是有顺序的,从小到大。那么我们可以用这个特性来做该题。
我们先中序遍历得到顺序vector,并且在此期间,通过比较数据是否相同获得出现最多次相同数值的个数maxnum。
随后我们设置两个指针left和right,他们两个下标的距离始终保持为maxnum,所以初始的left=0,right=left+maxnum-1,使得我们可以来循环判断(循环结束的条件是right超过范围):
1.如果v[left]和v[right]不相同,说明此时的left的数据不是最大相同数,left和right都往后加一
2.如果两个相同,说明该值就是我们需要的数,push_back到ret中,随后更新left为right+1,right更新为left+maxnum-1
class Solution {
public:
int maxnum = 0;
int num = 0;
int tmp = 0;
void GetVector(TreeNode* root,vector<int>& v)
{
if(root==nullptr)
return;
GetVector(root->left,v);
v.push_back(root->val);
if(tmp==root->val)
num++;
else
{
tmp=root->val;
num = 1;
}
if(maxnum<num)
maxnum = num;
GetVector(root->right,v);
}
vector<int> findMode(TreeNode* root) {
vector<int> v;
vector<int> ret;
GetVector(root,v);
int left = 0;
int right = left+maxnum-1;
while(right<v.size())
{
if(v[left++]!=v[right++])
{
ret.push_back(v[left]);
left=right+1;
right=left+maxnum-1;
}
else
{
left++;
right++;
}
}
return ret;
}
};
3.二叉树公共祖先
为了让上层节点知道下层的节点是否是p或者q,所以我们使用的遍历是后序遍历
1.如果root为空,返回空
2.如果root等于q或者p,说明此时节点是我们要返回的q或者p节点,那么我们此时要返回的是root
3.随后是后序遍历的左右递归,分别对left和right递归,并且获取由下传到上的节点
4.中间操作就是判断是否是我们要往上返回的:
如果左右都有,说明此时root就是公共祖先,那么我们返回root即可
如果右边有,左边没有,说明公共祖先在右边;或者找到了一个节点(q或者p任意一个),此时我们要返回的就是右节点
如果右边没有,左边有,其实思路是相同的,返回左节点
最后如果都不是,说明此时不是我们要的值,我们应该返回nullptr,告诉上层,下面没有找到p和q节点
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==nullptr)
return nullptr;
if(root==p||root==q)
return root;
TreeNode* left=lowestCommonAncestor(root->left,p,q);
TreeNode* right=lowestCommonAncestor(root->right,p,q);
if(left&&right)
return root;
if(!left&&right)
return right;
else if(left&&!right)
return left;
else
return nullptr;
}
};