leetcode——第501题——二叉搜索树中的众数

这篇博客介绍了如何在给定的二叉搜索树中找到所有众数的三种方法:通用递归法、BST递归法和迭代法。每种方法都详细阐述了其思路和关键步骤,包括如何统计节点出现的频率以及如何找到最大频率的节点。通过这些方法,可以有效地解决在BST中查找众数的问题。
摘要由CSDN通过智能技术生成

题目:
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

结点左子树中所含结点的值小于等于当前结点的值
结点右子树中所含结点的值大于等于当前结点的值
左子树和右子树都是二叉搜索树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
// /*******************法一::二叉树的通用 递归 方法*******************/
// private:
//     // 递归思路:根据题意,需要将整棵树都遍历一次,因此不需要返回值
//     // 因为要计算频率,因此定义map,来计算出现的频次即可,
//     // 这样的方法即使是非二叉搜索树也适用,先自己完成,后面在进行优化⑧~

//     // key = 节点的数值,  value = 该数值出现的次数
//     unordered_map<int,int> mp;
//     void travel(TreeNode* cur)
//     {
//         if(cur == nullptr)
//         {
//             return;
//         }
//         // 中序遍历     左 中 右
//         // 遍历过程中允许空节点进入递归逻辑
//         travel(cur->left);

//         mp[cur->val]++;

//         travel(cur->right);
//     }

// bool static cmp(const pair<int, int>& a, const pair<int, int>& b)
// {
//     return a.second > b.second;
// }

// public:
//     vector<int> findMode(TreeNode* root) 
//     {

// /***************************************************************/
// // 这里需要换一下思路,取最大频率的时候,应该能想到,对map中的 value 需要进行排序
// // 但是C++中,利用map或multimap可以对 key 进行排序,对value是无法排序的
// // 所以要么是把map换成vector再排序,要么不用map,直接用vector<pair<int,int>>类型
// // 别忘了 vector 也是可以放pair类型的数据的
//         // // 要找出 mp 中的最大 value
//         // vector<int> res;    // 赋值都不知道要赋什么值了
//         // int minVal = INT_MAX;
//         // for(auto& it : mp)
//         // {
//         //     // 这里判断也变得很 让人难受,这个方法行不通了
//         //     if(minVal > it.second)
//         //     {
//         //         minVal = it.second;
//         //     }

//         // }
// /***************************************************************/
//         travel(root);
//         vector<int> res;    // 记录结果值
//         vector<pair<int,int>> vec{mp.begin(),mp.end()}; // 初始化
//         sort(vec.begin(),vec.end(),cmp);    //对pair中的第二个元素排序
//         res.push_back(vec[0].first);
//         for(int i=1; i<vec.size(); i++)
//         {
//             if(vec[i].second == vec[0].second)
//             {
//                 res.push_back(vec[i].first);
//             }
//             // 因为已经按照频率排序了,所以一旦有不等于,
//             // 那么后面一定是小于,所以直接break即可,不要忘记这里的break
//             else
//             {
//                 break;
//             }
//         }
//         return res;
//     }

// /**************************法二::BST 递归法************************/
// private:
//     // 还需要定义一个统计频率的变量,就不用map容器了
//     int count;      // 统计频率
//     int maxCount;   // 统计最大频率
//     vector<int> result;
//     TreeNode* pre;
//     // 本写法不用map容器
//     // unordered_map<int, int> mp; // key表示节点值, value 表示出现次数
//     void travel(TreeNode* cur)
//     {
//         if(cur == nullptr)
//         {
//             return;
//         }
//         // 中序遍历:  左 中 右
//         travel(cur->left);
// /****************中节点的处理真的是精髓啊*******************************/
//         // 第一part:与pre节点进行比较,处理是否相等的情况,达到对频率更新的目的
//         if(pre == nullptr)  // 表示第一个节点
//         {
//             count = 1;
//         }
//         else if(pre->val == cur->val)   // 表示与前一个值相同
//         {
//             count++;
//         }
//         else    // 表示与前一个节点值不同
//         {
//             count = 1;
//         }
//         pre = cur;  // 更新上一个节点
//         // 第二part:对count和maxCount的对比,以达到更新结果集合的目的
//         if(count == maxCount)   // 如果和maxCount相同,则放入result
//         {
//             result.push_back(cur->val);
//         }
//         if(count > maxCount)    // 如果大于maxCount,则更新result和macCount
//         {
//             result.clear();
//             maxCount = count;
//             result.push_back(cur->val);
//         }
// /**************************************************************/
//         travel(cur->right);
//     }
// public:
//     vector<int> findMode(TreeNode* root)
//     {
//         // 注意类的成员变量在 private 里面一般只定义,不初始化
//         count = 0;
//         maxCount = 0;
//         pre = nullptr;
//         result.clear();

//         travel(root);
//         return result;
//     }

/************************法三::迭代法***************************/
public:
    vector<int> findMode(TreeNode* root)
    {
        int count = 0;
        int maxCount = 0;
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* pre = nullptr;
        if(root == nullptr)
        {
            return result;
        }
        st.push(root);
        while(!st.empty())
        {
            TreeNode* cur = st.top();
            if(cur != nullptr)
            {
                // 中序遍历 压栈顺序 右 中 左
                st.pop();
                if(cur->right != nullptr)
                {
                    st.push(cur->right);
                }
                st.push(cur);
                st.push(nullptr);
                if(cur->left != nullptr)
                {
                    st.push(cur->left);
                }
            }
            else
            {
                st.pop();
                cur = st.top();
                st.pop();

                // part1 比较节点
                if(pre == nullptr)
                {
                    count = 1;
                }
                else if(pre->val == cur->val)
                {
                    count++;
                }
                else
                {
                    count = 1;
                }
                // 在节点比较结束后,不要忘记更新 pre
                pre = cur;
                // part2 比较频率
                if(count == maxCount)
                {
                    result.push_back(cur->val);
                }
                if(count > maxCount)
                {
                    result.clear();
                    maxCount = count;
                    result.push_back(cur->val);
                }
            }
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值