【代码随想录】刷题Day21

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;
    }
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈里沃克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值