【力扣题解】P501-二叉搜索树中的众数-Java题解

news2024/12/30 2:13:36

花无缺

👨‍💻博客主页:@花无缺
欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
本文由 花无缺 原创

收录于专栏 【力扣题解】


文章目录

  • 【力扣题解】P501-二叉搜索树中的众数-Java题解
    • 🌏题目描述
    • 💡题解
    • 🌏总结


【力扣题解】P501-二叉搜索树中的众数-Java题解

P501-二叉搜索树中的众数

🌏题目描述

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

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

假定 BST 满足如下定义:

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

示例 1:

在这里插入图片描述

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

示例 2:

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

提示:

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

💡题解

递归

// 节点值的最大出现频率
int maxCount = Integer.MIN_VALUE;
// 统计频率
int count = 0;
List<Integer> res = new LinkedList<>();
// 保存上一个遍历的节点
TreeNode pre = null;
public int[] findMode(TreeNode root) {
    dfs(root);
    int[] a = new int[res.size()];
    for (int i = 0; i < a.length; i++) {
        a[i] = res.get(i);
    }
    return a;
}
public void dfs(TreeNode root) {
    if (root == null) {
        return;
    }
    dfs(root.left);
    // 当前节点是第一个节点, count 为 1
    if (pre == null) {
        count = 1;
    //     当前节点和前一个节点值相同, count++
    } else if (pre.val == root.val) {
        count++;
    //     当前节点和前一个节点不同, count 变为 1
    } else {
        count = 1;
    }
    // 更新 pre 节点
    pre = root;
    // 如果当前统计到的节点值次数和最大节点值次数相同
    // 就放入列表 res
    if (count == maxCount) {
        res.add(root.val);
    }
    // 如果 count > maxCount, 那么就更新 maxCount
    // 然后先清空 res, 再将当前节点值加入列表 res
    if (count > maxCount) {
        maxCount = count;
        res.clear();
        res.add(root.val);
    }
    dfs(root.right);
}

迭代

public int[] findMode(TreeNode root) {
    Deque<TreeNode> stack = new LinkedList<>();
    TreeNode cur = root;
    TreeNode pre = null;
    // 节点值的最大出现频率
    int maxCount = Integer.MIN_VALUE;
    // 统计频率
    int count = 0;
    List<Integer> res = new LinkedList<>();
    while (!stack.isEmpty() || cur != null) {
        if (cur != null) {
            stack.offerLast(cur);
            cur = cur.left;
        } else {
            cur = stack.pollLast();
            // 当前节点是第一个节点, count 为 1
            if (pre == null) {
                count = 1;
                //     当前节点和前一个节点值相同, count++
            } else if (pre.val == cur.val) {
                count++;
                //     当前节点和前一个节点不同, count 变为 1
            } else {
                count = 1;
            }
            // 更新 pre 节点
            pre = cur;
            // 如果当前统计到的节点值次数和最大节点值次数相同
            // 就放入列表 res
            if (count == maxCount) {
                res.add(cur.val);
            }
            // 如果 count > maxCount, 那么就更新 maxCount
            // 然后先清空 res, 再将当前节点值加入列表 res
            if (count > maxCount) {
                maxCount = count;
                res.clear();
                res.add(cur.val);
            }
            cur = cur.right;
        }
    }
    int[] a = new int[res.size()];
    for (int i = 0; i < a.length; i++) {
        a[i] = res.get(i);
    }
    return a;
}

时间复杂度:O(n),需要遍历二叉搜索树的所有节点,节点数为 n。

🌏总结

这个题要求我们查找二叉搜索树中的众数,也就是出现次数最多的一个或者多个节点值,按照一般的做法,我们会将二叉搜索树的节点值放到一个数组中,对数组进行排序,然后使用双指针遍历来获取数组中的众数,但是此题我们可以直接在遍历的过程中获取众数,为什么呢?因为根据二叉搜索树的特性,我们知道二叉搜索树的中序序列是一个有序的递增序列,所以我们可以在中序遍历二叉搜索树的时候同时对节点进行操作,从而获取到众数。

同样,在处理节点时,我们采用双指针法,pre 指向上一个遍历过的节点,然后使用当前节点和 pre 指向的节点进行比较,如果相等,则统计变量 count++,否则重置为 1,当然要注意,当我们遍历第一个节点的时候,pre 为 null,这时候 count 也为 1,也就是当前节点出现了一次。

然后每一次遍历之后,我们要将当前节点频次 count 和最大频次 maxCount 作比较,只要相等,就将当前节点值加入结果列表 res,但是有可能当前节点的频次还会增多,这怎么办呢?这就要到一下步骤了,如果当前频次 count 大于 maxCount,那么就更新 maxCount,接着我们要清空 res,这样就避免了出现错误结果的情况,然后将当前节点值加入 res。

以上我也给出了迭代法的代码,和递归代码的逻辑是完全一样的。

作者:花无缺(huawuque404.com)


🌸欢迎关注我的博客:花无缺-每一个不曾起舞的日子都是对生命的辜负~
🍻一起进步-刷题专栏:【力扣题解】
🥇往期精彩好文:
📢【全网最全爱心代码仓库】
📢【CSS选择器全解指南】
📢【HTML万字详解】
你们的点赞👍 收藏⭐ 留言📝 关注✅
是我持续创作,输出优质内容的最大动力!
谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1352883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文本表示模型简介

文本是一类非常重要的非结构化数据&#xff0c;如何表示文本数据一直是机器学习领域的一个重要研究方向。那么有哪些文本表示模型&#xff1f;以及它们各有什么优缺点&#xff1f; 1. 常见的文本表示模型 1.1. 词袋模型和N-gram模型 最基础的文本表示模型是词袋模型。顾名思…

Java最新技术介绍和分析 (202305)

说明&#xff1a;本文完成了2023年5月份&#xff0c;当时最新的LTS版本是Java17&#xff0c;本文在撰写时参考了美团技术团队和阿里JDK团队相关的文章&#xff0c;以及本文也引了用文章中的图片。在此表示感谢&#xff01; Java版本火车 相信老牌的Java开发者和爱好者把Java的…

计算机创新协会冬令营——暴力枚举题目01

首先是欢迎大家参加此次的冬令营&#xff0c;我们协会欢迎所有志同道合的同学们。话不多说&#xff0c;先来看看今天的题目吧。 题目 力扣题号&#xff1a;2351. 第一个出现两次的字母 注&#xff1a;下述题目和示例均来自力扣 题目 给你一个由小写英文字母组成的字符串 s &…

(ros2)控制gazebo移动的话题:

gazebo并不是ros2内自带的&#xff0c;是一个独立的软件&#xff0c;需要安装ros_gz功能被把ros2消息转换为gazebo可以识别的命令&#xff0c;并且把gazebo状态转换为ros2信息&#xff0c;所以可以认为ros_gz_bridge节点就是gazebo&#xff0c; 这个节点只接收2个话题&#xf…

Yarn的安装与使用详细介绍

什么是yarn Apache Hadoop YARN &#xff08;Yet Another Resource Negotiator&#xff0c;另一种资源协调者&#xff09;是一种新的 Hadoop 资源管理器&#xff0c;它是一个通用资源管理系统&#xff0c;可为上层应用提供统一的资源管理和调度&#xff0c;它的引入为集群在利用…

2024年天津仁爱学院专升本专业课考试考场安排及准考证打印的通知

天津仁爱学院2024年高职升本科专业课考试通知 一、考试科目及时间 天津仁爱学院2024年高职升本科专业课考试定于2024年1月9日9&#xff1a;00-14&#xff1a;00举行。考试地点&#xff1a;天津市静海区团泊新城博学苑&#xff0c;天津仁爱学院。具体考试科目时间安排如下表&a…

提高工作效率的Postman环境变量使用方法

在 Postman 中&#xff0c;用 Environments 来管理环境变量。我们在开发的过程中&#xff0c;往往会用到多个环境&#xff1a;开发环境&#xff0c;测试环境&#xff0c;UAT 环境&#xff0c;生产环境等。我们要调用不同环境的 API 时&#xff0c;只需切换 Postman 的 Environm…

ISP 基础知识积累

Amber&#xff1a;现有工作必要的技术补充&#xff0c;认识需要不断深入&#xff0c;这个文档后续还会增加内容进行完善。 镜头成像资料 ——干货满满&#xff0c;看懂了这四篇文章&#xff0c;下面的问题基本都能解答 看完思考 1、ISP 是什么&#xff0c;有什么作用&#xff…

php安装扩展event 提示 No package ‘openssl‘ found 解决方法

在使用pecl编译安装最新版event模块的时候提示 No package openssl found , 可是本机是安装了openssl的, 编译时找不到, 大概率就是环境配置的问题了, 增加 OPENSSL_CFLAGS OPENSSL_LIBS环境变量即可解决. 异常提示信息: checking for openssl > 1.0.2... no configure: …

【数据库原理】(5)关系数据库的关系数据结构

关系及相关概念 在关系模型中,无论是实体还是实体之间的联系均由关系(二维表)来表示。 1.域&#xff08;Domain&#xff09; 定义&#xff1a;域是一组具有相同数据类型的值的集合。例子&#xff1a;实数集合、整数集合、英文字母集合等。 2.笛卡儿积&#xff08;Cartesian…

学习Vue单文件组件总结

今天主要学习了组件实例对象的一个重要内置关系和单文件组件。先说一下实例对象的内置关系&#xff0c;在这里要对JS中的原型链有一定的基础&#xff0c;Vue构造函数的prototype原型指向的是Vue的原型对象&#xff0c;new出来的Vue实例对__proto__同样指向的是Vue的原型对象&am…

Hex 文件类型字段详解

文章目录 地址类型字段详解02&#xff08;扩展段地址记录&#xff09;&#xff1a;指定后续数据记录的向左移动4位后开始计算地址04&#xff08;扩展线性地址记录&#xff09;&#xff1a;指定后续数据记录的起始地址的高16位 地址类型字段详解 02&#xff08;扩展段地址记录&…

18、BLIP

简介 github BLIP提出了一种基于预训练的方法&#xff0c;通过联合训练视觉和语言模型来提升多模态任务的性能。 BLIP(Bootstrapping Language-Image Pretraining)是salesforce在2022年提出的多模态框架&#xff0c;是理解和生成的统一&#xff0c;引入了跨模态的编码器和解码…

RocketMQ5.0延时消息时间轮算法

前言 RocketMQ 相较于其它消息队列产品的一个特性是支持延时消息&#xff0c;也就是说消息发送到 Broker 不会立马投递给消费者&#xff0c;要等待一个指定的延迟时间再投递&#xff0c;适用场景例如&#xff1a;下单后多长时间没付款系统自动关闭订单。 RocketMQ 4.x 版本的延…

【LeetCode-剑指offer】-- 9.乘积小于K的子数组

9.乘积小于K的子数组 方法&#xff1a;滑动窗口 关于为什么子数组数目为j-11。这时候就要理解采用滑动窗口的思路其实是枚举子数组的右端点&#xff0c;然后来找到满足条件的最小左端点。也即当得到满足条件的窗口时&#xff0c;就意味着得到了以 j 作为右端点时满足条件的左端…

框架的灵魂之笔-反射

反射&#xff1a;框架的灵魂 类加载器 概述&#xff1a;当程序要使用某个类的时候&#xff0c;如果该类还未被加载到内存中&#xff0c;则系统会通过以下三个步骤 ①类的加载 ②类的连接 ③类的初始化来对类进行初始化。如果不出现意外情况&#xff0c;JVM将会连续完成这三个步…

momentjs计算两个时间差返回时分秒

// 导入 Moment.js 模块 const moment require(moment);// 定义起始时间和结束时间 const startTime 2021-09-30T14:30:00; // 格式必须符合 ISO8601&#xff08;YYYY-MM-DDTHH:mm:ss&#xff09; const endTime 2021-09-30T15:45:00;// 创建 Moment.js 对象来表示起始时间和…

CentOS 7 实战指南:文本处理命令详解

前言 在Linux系统中&#xff0c;文本处理是非常基础却又必不可少的一项技能。如果你正在使用CentOS系统&#xff0c;那么学会如何利用文本操作命令来高效地处理文本文件无疑将会是一个强有力的工具。 本篇文章将介绍一些最常用和最实用的文本操作命令&#xff0c;并通过详尽的…

如何自动生成 API 接口文档 - 一份详细指南

本篇文章详细教你如何使用 Apifox 的 IDEA 插件实现自动生成接口代码。好处简单总结有以下几点&#xff1a; 自动生成接口文档&#xff1a; 不用手写&#xff0c;一键点击就可以自动生成文档&#xff0c;当有更新时&#xff0c;点击一下就可以自动同步接口文档&#xff1b;代码…

金和OA UserWebControl.UserSelect.ashx 信息泄露漏洞

产品简介 金和网络是专业信息化服务商&#xff0c;为城市监管部门提供了互联网监管解决方案&#xff0c;为企事业单位提供组织协同OA系统升开发平台&#xff0c;电子政务一体化平台智慧电商平合等服务 漏洞概述 金和OA UserWebControl.UserSelect.AjaxServiceMethod,UserWeb…