zoukankan      html  css  js  c++  java
  • 501. 二叉搜索树中的众数

    501. 二叉搜索树中的众数

    题目链接:501. 二叉搜索树中的众数(简单)

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

    假定 BST 有如下定义:

    • 结点左子树中所含结点的值小于等于当前结点的值

    • 结点右子树中所含结点的值大于等于当前结点的值

    • 左子树和右子树都是二叉搜索树

    例如: 给定 BST [1,null,2,2],

       1
      \
        2
      /
      2

    返回[2].

    提示:如果众数超过1个,不需考虑输出顺序

    进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)

    解题思路

    如果该数只是普通的二叉树,那最简单的方法就是遍历这棵树,并用 map 统计频率,最后对频率进行排序,取出频率高的元素集合即可。但需要注意:C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序。所以需要将map转化数组即vector,再进行排序,当然vector里面放的也是pair<int, int>类型的数据,第一个int为元素,第二个int为出现频率。

    二叉搜索树是中序遍历有序的二叉树,所以可以将二叉搜索树的中序遍历结果存入一个数组中,再对数组中相邻两个元素作比较,最后输出频率高的元素的集合。

    这里我们考虑不适用额外空间的方法,直接对树进行操作。关键点就在于要将中序遍历中 当前节点的 前一个节点 记录下来。可以参考530. 二叉搜索树的最小绝对差

    方法一:递归

    代码

    C++
    // 递归
    class Solution {
    public:
        int maxFre = 0;
        int curFre = 0;
        vector<int> maxVec;
        TreeNode* preNode = nullptr;
        void traversal(TreeNode* curNode) {
            if (curNode == nullptr) return;
            traversal(curNode->left); //
    //处理频率
            if (preNode == nullptr) {
                curFre = 1;
            } else if (curNode->val == preNode->val) {
                curFre++;
            } else {
                curFre = 1;
            }
            // 将频率大的放入数组中
            if (curFre > maxFre) {
                maxFre = curFre; // 这里会重新给 maxFre 赋值
                maxVec.clear();
                maxVec.push_back(curNode->val);
            } else if (curFre == maxFre) {
                maxVec.push_back(curNode->val);
            }
    ​
            preNode = curNode;
    ​
            traversal(curNode->right); //
        }
        vector<int> findMode(TreeNode* root) {
            maxFre = 0;
            curFre = 0;
            preNode = nullptr;
            maxVec.clear();
            traversal(root);
            return maxVec;
        }
    };
    JavaScript
    // 递归
    var findMode = function(root) {
        let curFre = 0;
        let maxFre = 0;
        let maxVec = [];
        let preNode = null;
        const traversal = (curNode) => {
            if (curNode === null) return;
            traversal(curNode.left);
            if (preNode === null) {
                curFre = 1;
            } else if (preNode.val === curNode.val) {
                curFre++;
            } else {
                curFre = 1;
            }
            if (curFre > maxFre) {
                maxFre = curFre;
                maxVec = [];
                maxVec.push(curNode.val);
            } else if (curFre === maxFre) {
                maxVec.push(curNode.val);
            }
            preNode = curNode;
            traversal(curNode.right);
        }
        traversal(root);
        return maxVec;
    };

    方法二:迭代

    代码

    C++
    // 迭代(中序遍历)
    class Solution2 {
    public:
        vector<int> findMode(TreeNode* root) {
            int maxFre = 0;
            int curFre = 0;
            vector<int> maxVec;
            TreeNode* preNode = nullptr;
            TreeNode* curNode = root;
            stack<TreeNode*> nodeSta;
            while (curNode || !nodeSta.empty()) {
                if (curNode) { //
                    nodeSta.push(curNode);
                    curNode = curNode->left;
                } else {
                    curNode = nodeSta.top();
                    nodeSta.pop();
                    ////处理频率
                    if (preNode == nullptr) {
                        curFre = 1;
                    } else if (curNode->val == preNode->val) {
                        curFre++;
                    } else {
                        curFre = 1;
                    }
                    // 将频率大的放入数组中
                    if (curFre > maxFre) {
                        maxFre = curFre; // 这里会重新给 maxFre 赋值
                        maxVec.clear();
                        maxVec.push_back(curNode->val);
                    } else if (curFre == maxFre) {
                        maxVec.push_back(curNode->val);
                    }
                    preNode = curNode;
    ​
                    //
                    curNode = curNode->right;
                }
            }
            return maxVec;
        }
    };
    JavaScript
    // 迭代
    var findMode = function(root) {
        let curFre = 0;
        let maxFre = 0;
        let maxVec = [];
        let preNode = null;
        let nodeSta = [];
        let curNode = root;
        while(curNode || nodeSta.length != 0) {
            if (curNode) {
                nodeSta.push(curNode);
                curNode = curNode.left;
            } else {
                curNode = nodeSta.pop();
                if (preNode === null) {
                    curFre = 1;
                } else if (preNode.val === curNode.val) {
                    curFre++;
                } else {
                    curFre = 1;
                }
                if (curFre > maxFre) {
                    maxFre = curFre;
                    maxVec = [];
                    maxVec.push(curNode.val);
                } else if (curFre === maxFre) {
                    maxVec.push(curNode.val);
                }
                preNode = curNode;
                curNode = curNode.right;
            }
        }
        return maxVec;
    };

     

     

  • 相关阅读:
    关于HashMap的线程安全问题
    Java利器之UML类图详解
    mongoDB4.0数据库
    requests-html库render的使用
    爬虫最新的库requests-html库总结
    爬虫多次爬取时候cookie的存储用于登入
    requests模块响应体属性和方法重新整理
    Visual Studio 代码补全功能有时候会失效的原因
    C++Primer笔记——文本查询程序(原创,未使用类)
    Clion 常用快捷键
  • 原文地址:https://www.cnblogs.com/wltree/p/15686787.html
Copyright © 2011-2022 走看看