二叉搜索树中的众数


文章内容是自己刷leetcode题目的一些总结。
文章内容参考公众号: 代码随想录
喜欢的话,希望大家可以点点赞 ^ - ^

一.题目描述

在这里插入图片描述

二.题目分析

因为是二叉搜索树,我们依旧可以用验证二叉搜索树中提到的两种方法进行分析。

这里使用两种指针的方法进行求解。

因为我们要找的是众数,二叉搜索树的中序遍历又是有序的,仍然采用中序遍历。

我们用两个指针分别记录当前节点的数值和前一个结点的数值。如果这两个数值相同,给count ++,如果两个数值不相同,count = 1。count记录的是当前数值的个数。

我们记录一个maxcount,当count的值等于maxcount时,将该结果加入ans中;当count的值大于maxcount时,就需要更新结果,应该清除ans,然后将当前节点的数值放进去。maxcount记录的是众数的数值对应的个数。

三.中序遍历递归代码

代码中也有详细的思路与注释。

class Solution {

public:

    int count = 0, maxcount = 0;
    TreeNode* pre = nullptr;
    vector<int> ans;

    void trevasal(TreeNode* cur) {
        if(cur == nullptr) return ;
        trevasal(cur->left); //左
                             //中
        if(pre == nullptr) { //第一个节点
            count = 1;
        } else if(pre->val == cur->val) { //前后节点值相同
            count ++;
        } else { //前后节点值不同
            count = 1;
        }
        pre = cur;

        if(count == maxcount) { //是当前最大频数,加入结果
            ans.push_back(cur->val);
        }
        if(count > maxcount) { //不是当前最大频数,更新最大频数,清空结果,重新加入
            maxcount = count;
            ans.clear();
            ans.push_back(cur->val);
        }

        trevasal(cur->right); //右
        

    }

    vector<int> findMode(TreeNode* root) {
        //如果是二叉搜索树,不是一般的二叉树,思路如下
        //1.中序遍历二叉树,遍历结果是递增有序的
        //2.统计当前节点的值出现的次数,并将当前节点加入到结果中,用到pre与cur指针
        //3.我们可能会遇到频数更高的节点值,更新最大频数,清空结果重新加入
        //使用上述方法我们只遍历了一次二叉树
        //如果我们先遍历一次统计频数,再遍历一次加入结果,需要遍历两次
        
        

        ans.clear();
        trevasal(root);
        return ans;
    }
};

四.拓展:如果二叉树不是二叉搜索树

1.解题思路

如果只是一般的二叉树,他没有中序遍历递增的性质,那么我们选择哪一种遍历方式都可以。

我们要统计众数,这里使用map,记录每个节点的频率。

将map按照频率由大到小排序,那么map中第一个元素就是众数,和第一个元素频率相同的后续元素也是众数。

2.递归代码

class Solution {

public:

    unordered_map<int, int> myMap;

    void trevasal(TreeNode* root) { //前序遍历统计频率
        if(root == nullptr) return ;
        myMap[root->val] ++;
        trevasal(root->left);
        trevasal(root->right);
        return ;
    }

    bool static cmp(const pair<int, int>& a, const pair<int, int>& b) {
        return a.second > b.second; //按照第二个元素从大到小排序
    }

    vector<int> findMode(TreeNode* root) {
        //如果不是二叉搜索树,而是一般的二叉树,思路如下
        //1.遍历,用map统计频率
        //2.将频率转化为数组进行从大到小排序
        //3.统计频率最大的节点值并返回
        vector<int> ans;
        trevasal(root);

        vector<pair<int, int>> vec(myMap.begin(), myMap.end());
        sort(vec.begin(), vec.end(), cmp);

        
        ans.push_back(vec[0].first);
        for(int i = 1; i < vec.size(); i ++) {
            if(vec[i].second == vec[0].second) {
                ans.push_back(vec[i].first);
            } else {
                break;
            }
        }
        return ans;
    }
};

五.总结

利用二叉搜索树的中序遍历递增的性质,我们可以很方便的解决许多问题。

在从特殊的二叉搜索树中寻找众数到从一般的二叉树中寻找众数,用到了不同的思路,这与树本身的性质有关,不过核心思想都是统计频率,寻找最大频率。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Echo夏末

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

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

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

打赏作者

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

抵扣说明:

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

余额充值