力扣第501题 二叉树的众数 c++ (暴力 加 双指针优化)

这篇具有很好参考价值的文章主要介绍了力扣第501题 二叉树的众数 c++ (暴力 加 双指针优化)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目

501. 二叉搜索树中的众数

简单

相关标签

树   深度优先搜索   二叉搜索树   二叉树

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

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

示例 1:

力扣第501题 二叉树的众数 c++ (暴力 加 双指针优化),leetcode,二叉数,数据结构,算法,leetcode,c++,二叉树,暴力

输入:root = [1,null,2,2]
输出:[2]

示例 2:

输入:root = [0]
输出:[0]

提示:

  • 树中节点的数目在范围 [1, 104] 内
  • -105 <= Node.val <= 105

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

思路和解题方法一(暴力)

  1. 定义一个私有函数searchBST,用于前序遍历二叉搜索树,并统计每个元素的频率。函数参数包括当前节点指针cur和存储元素频率的unordered_mapmap
  2. searchBST函数中,如果当前节点为空,则直接返回;否则,对当前节点的值进行统计,将当前节点的值作为map的键,并将对应的值加1,表示该元素出现的频率。
  3. 递归调用searchBST函数,传入当前节点的左子节点和map,再传入当前节点的右子节点和map,实现前序遍历。
  4. 定义一个静态成员函数cmp,用于比较两个pair类型的元素,按照频率降序排列。在排序时使用此比较函数。
  5. findMode函数中,首先创建一个空的unordered_map类型的map,用于存储元素及其频率。
  6. 如果输入的根节点为空,直接返回空的结果数组。
  7. 调用searchBST函数,传入根节点和map,统计二叉搜索树中每个元素的频率。
  8. map转化为vector类型,并使用sort函数对vector进行排序,排序方式为按照元素的频率降序排列。
  9. 创建一个空的结果数组result,将排序后的第一个元素的键(也就是出现频率最高的元素)添加到result中。
  10. 遍历排序后的vector,从第二个元素开始,如果其频率和第一个元素的频率相同,则将其键添加到result中;否则结束遍历。
  11. 返回结果数组result

复杂度

        时间复杂度:

                O(n logn)

  • 时间复杂度:

    • 前序遍历二叉树的时间复杂度为 O(n),其中 n 是二叉树的节点数。
    • 构建哈希表的过程中,对每个节点进行插入操作的平均时间复杂度为 O(1)。因此构建哈希表的时间复杂度也是 O(n)。
    • 对哈希表进行排序的时间复杂度为 O(nlogn)。
    • 综上所述,算法的时间复杂度为 O(n) + O(n) + O(nlogn) = O(nlogn)。

        空间复杂度

                O(n)

  • 空间复杂度:

    • 使用了一个哈希表来存储元素及其频率,哈希表的空间复杂度是 O(n)。
    • 将哈希表转换成了向量,空间复杂度仍然是 O(n)。
    • 保存结果的向量,最多可能存储所有节点的值,因此空间复杂度也是 O(n)。
    • 综上所述,算法的空间复杂度为 O(n)。

c++ 代码

class Solution {
private:
    // 前序遍历二叉搜索树,统计每个元素的频率
    void searchBST(TreeNode* cur, unordered_map<int, int>& map) {
        if (cur == NULL) return ;
        map[cur->val]++; // 统计元素频率
        searchBST(cur->left, map); // 遍历左子树
        searchBST(cur->right, map); // 遍历右子树
        return ;
    }
    // 静态成员函数,用于比较两个pair类型元素,按照频率降序排列
    static bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
        return a.second > b.second;
    }
public:
    vector<int> findMode(TreeNode* root) {
        unordered_map<int, int> map; // 存储元素及其频率的map,key为元素,value为频率
        vector<int> result; // 结果数组
        if (root == NULL) return result; // 根节点为空,直接返回空结果数组
        searchBST(root, map); // 统计二叉搜索树中每个元素的频率
        vector<pair<int, int>> vec(map.begin(), map.end()); // 将map转换为vector
        sort(vec.begin(), vec.end(), cmp); // 按照频率降序排列
        result.push_back(vec[0].first); // 将频率最高的元素添加到结果数组中
        for (int i = 1; i < vec.size(); i++) {
            // 遍历排序后的vector,如果元素频率与第一个元素的频率相同,则添加到结果数组中;否则结束遍历
            if (vec[i].second == vec[0].second) result.push_back(vec[i].first);
            else break;
        }
        return result; // 返回结果数组
    }
};

 思路和解题方法二(双指针 加 时时优化)

  1. 使用了一个全局变量 maxCount 来记录最大频率,使用 count 来统计当前节点值出现的频率。同时,引入了一个 pre 变量来记录前一个访问的节点,以便比较当前节点与前一个节点的值是否相同。
  2. 函数 searchBST 是进行中序遍历的辅助函数,通过递归遍历左子树、处理当前节点、递归遍历右子树的顺序进行搜索。在处理当前节点时,首先判断当前节点值与前一个节点值是否相同,若相同则将 count 增加 1,否则将 count 重置为 1。然后,根据 count 的大小与 maxCount 进行比较,并更新 maxCountresult。如果 countmaxCount 相同,说明当前节点值出现的频率与最大频率相同,将其加入 result 中。如果 count 大于 maxCount,则更新 maxCount 并清空 result,将当前节点值放入 result 中。
  3. findMode 函数中,初始化各个变量,然后调用 searchBST 开始搜索,并返回结果数组 result

复杂度

        时间复杂度:

                O(n)

时间复杂度是O(n),其中n是二叉搜索树中的节点数。因为我们需要遍历所有的节点来统计它们的频率。

        空间复杂度

                O(1)

不利用额外空间

c++ 代码

class Solution {
private:
    int maxCount = 0; // 最大频率
    int count = 0; // 统计频率
    TreeNode* pre = NULL; // 前一个节点
    vector<int> result; // 存储结果的向量

    // 中序遍历二叉搜索树,搜索出现频率最高的节点值
    void searchBST(TreeNode* cur) {
        if (cur == NULL) return; // 递归终止条件,当前节点为空

        searchBST(cur->left); // 左子树

        // 统计频率
        if (pre == NULL) { // 第一个节点
            count = 1;
        } else if (pre->val == cur->val) { // 与前一个节点数值相同
            count++;
        } else { // 与前一个节点数值不同
            count = 1;
        }
        pre = cur; // 更新上一个节点

        if (count == maxCount) { // 如果和最大频率相同,将节点值放进result中
            result.push_back(cur->val);
        }

        if (count > maxCount) { // 如果频率大于最大频率
            maxCount = count;   // 更新最大频率
            result.clear();     // 清空result,之前result中的元素都无效了
            result.push_back(cur->val);
        }

        searchBST(cur->right); // 右子树

        return ;
    }

public:
    vector<int> findMode(TreeNode* root) {
        count = 0;
        maxCount = 0;
        pre = NULL; // 初始化前一个节点为空
        result.clear(); // 清空result向量

        searchBST(root); // 调用中序遍历函数搜索出现频率最高的节点值

        return result; // 返回结果向量
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。文章来源地址https://www.toymoban.com/news/detail-726594.html

到了这里,关于力扣第501题 二叉树的众数 c++ (暴力 加 双指针优化)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LeetCode 501. 二叉搜索树中的众数【二叉搜索树中序遍历+Morris遍历】简单

    本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,

    2024年02月06日
    浏览(31)
  • 力扣第236题——二叉树的最近公共祖先 (C语言题解)

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大( 一个节点也可以是它自己的祖先 )。” 示例 1: 示例 2: 示例

    2024年01月20日
    浏览(31)
  • C++力扣题目104--二叉树的最大深度

    给定一个二叉树,找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。 示例: 给定二叉树 [3,9,20,null,null,15,7], 返回它的最大深度 3 。 看完本篇可以一起做了如下两道题目: 104.二叉树的最大深度(opens n

    2024年01月16日
    浏览(53)
  • 力扣(144. 二叉树的前序遍历&&94.二叉树的中序遍历&&145. 二叉树的后序遍历)

    题目链接 题目1: 思路:较简单的思路,就是先将左孩子全部入栈,然后出栈访问右孩子,右孩子为空,再出栈,不为空,右孩子入栈,然后再次循环访问左孩子。 题目链接 题目2: 思路:同前序遍历一样,只不过访问结点,改为出栈时访问。 题目3链接 题目3: 思路1:同样

    2024年01月19日
    浏览(42)
  • 【力扣 - 二叉树的最大深度】

    给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 树中节点的数量在 [0, 10^4] 区间内。 如果我们知道了左子树和右子树的最大深度 l 和 r ,那么该二叉树的最大深度即为 而左子树和右子树的最大深度又可以以

    2024年02月21日
    浏览(29)
  • 力扣 257. 二叉树的所有路径

    题目来源:https://leetcode.cn/problems/binary-tree-paths/description/    C++题解1:使用递归,声明了全局变量result,遇到叶子节点就将字符串添加到result中。 递归三步法: 1. 确认传入参数:当前节点+已有路径(字符串); 2. 确认终止条件:遇到叶子节点,即左右节点都为空时,将当前

    2024年02月11日
    浏览(30)
  • 【力扣 - 二叉树的中序遍历】

    给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 树中节点数目在范围 [0, 100] 内 首先我们需要了解什么是二叉树的中序遍历:按照访问左子树——根节点——右子树的方式遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历完整棵树。因

    2024年02月22日
    浏览(32)
  • 力扣第96题 不同的二叉搜索树 c++ 二叉搜索树 动态规划 + 数学思维

    96. 不同的二叉搜索树 中等 相关标签 树   二叉搜索树   数学   动态规划   二叉树 给你一个整数  n  ,求恰由  n  个节点组成且节点值从  1  到  n  互不相同的  二叉搜索树  有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 示例 2: 提示: 1 = n = 19 vectorint

    2024年02月06日
    浏览(25)
  • 力扣236——二叉树的最近公共祖先

    祝大家新年快乐呀,虽这段时间正值过年,但是我们不要忘记停下学习的脚步。今天我们一起看一到力扣上的经典二叉树OJ题,求二叉树两个结点最近的公共祖先。 https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/description/ 链接给大家放在这里啦,大家一点即达 首先我们

    2024年02月20日
    浏览(32)
  • 二叉树的前序遍历(力扣144)

    目录 题目描述: 解法一:递归法 解法二:迭代法 解法三:Morris 遍历 二叉树的前序遍历 给你二叉树的根节点  root  ,返回它节点值的  前序   遍历。 示例 1: 示例 2: 示例 3: 示例 4: 示例 5: 提示: 树中节点数目在范围  [0, 100]  内 -100 = Node.val = 100 复杂度分析 时间复

    2023年04月17日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包