代码随想录算法训练营 DAY 21 | 230.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236.二叉树的最近公共祖先

news2024/11/18 4:30:49

230.二叉搜索树的最小绝对差

  • 二叉搜索树,用中序遍历

用一个全局变量result存储最小绝对差,prev指针存储

在中的逻辑里去更新result(保证prev不为空),然后更新prev=cur。

牢记谦虚遍历的顺序!pre紧跟在cur后面移动

class Solution {
    int result = Integer.MAX_VALUE;  //记录绝对差
    TreeNode prev = null;
    public void inorder(TreeNode cur) {
        if(cur == null) return;
        inorder(cur.left);
        
        //中
        if(prev!=null) {
            result = Math.min(result, Math.abs(prev.val-cur.val));
        }
        prev = cur; //进到下一层递归之前,prev就等于cur

        inorder(cur.right);
    }

    public int getMinimumDifference(TreeNode root) {
        inorder(root);
        return result;
    }
}

501.二叉搜索树中的众数

  • 二叉搜索树,一定是中序遍历
  • 二叉搜索的性质,众数一定是连续出现的!—用双指针

怎么在一次遍历里找到maxCount和对应的数?

如果最后count=maxCount,就把这个元素放到result数组里。

定义全局变量

pre = null; int count = 0;   //count统计单个元素出现的频率
int maxCount = 0;   //统计遍历过的二叉树里元素出现的最高频率
List<Integer> result;
  1. 确定递归函数
void traversal(TreeNode cur)
  1. 终止条件
if(cur == null) return;
  1. 单层递归逻辑 中序 左中右

单层处理的逻辑:

  • 一进来先更新count,分为三种情况
  • 然后更新pre指针(此时pre就等于cur了)
  • 接着看目前的count是否大于maxCount了。相等就加入result,更大了就清空result然后加入
  • 为什么加的是cur.val而不是pre.val?下面这个时候,在count++完,pre还没更新的时候,cur是指向3的!此时count=2 所以到后面加入result数组的是cur.val!

在这里插入图片描述

traversal(cur.left);  //左

//中 就是处理的逻辑
if(pre == null) {   //固定操作,说明刚开始遍历 cur指向第一个元素
    count = 1;
}else if(pre.val == cur.val) {  //pre不为空了,这个元素重复出现了
    count++;
}else {  //说明当前数值不相等了 cur第一次出现 count重置为1
    count = 1;
}
pre = cur;  //更新pre,跟着cur移动
if(count == maxCount) result.add(cur.val);  //如果这个数出现频率和maxCount相等,放进去
else if(count > maxCount) {
    maxCount = count;  //更新maxCount
    result.clear();  //清空result数组,之前旧的元素都不对了!
    result.add(cur.val);
}

traversal(cur.right);  //右

所谓的双指针就是,pre先初始化为null,两个指针同步遍历(pre更新就直接pre=cur)

通过判断count是否大于maxCount来添加元素,如果大于了就清空重新放。

  • 完整代码
class Solution {
    List<Integer> result = new ArrayList<>();
    TreeNode pre = null;
    int maxCount = 0;
    int count = 0;

    public void traversal(TreeNode cur) {
        if(cur == null) return;
        traversal(cur.left);

        if(pre == null) {
            count = 1;
        }else if(pre.val == cur.val) {
            count++;
        }else {
            count = 1;
        }
        pre = cur;
        if(count == maxCount) {
            result.add(cur.val);
        }else if(count > maxCount) {
            maxCount = count;
            result.clear();
            result.add(cur.val);
        }

        traversal(cur.right);
    }

    public int[] findMode(TreeNode root) {
        traversal(root);
        int[] res = new int[result.size()];
        for (int i = 0; i < result.size(); i++) {
            res[i] = result.get(i);
        }
        return res;
    }
}

236.二叉树的最近公共祖先

注意:一个节点也可以是它自己的祖先

  • 怎么从下往上遍历?

回溯啊!后序遍历的回溯过程。

判断某一个节点,左子树有没有出现过p,右子树有没有出现过q

只要左右子树出现了p和q就往上返回,如果左不为空右不为空的话就是最近的公共祖先

第二种情况:自己是自己的祖先

  1. 递归函数
TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
  1. 确定终止条件

遇到空了 or 遇到了p或q,返回

if(root == null) return root;
if(root == p || root == q) return root;
  1. 单层递归逻辑 后序左右中
left = traversal(root.left,p,q); //相当于告诉我们左子树有没有出现过p q
right = traversal(root.right,p,q);

//左右都不为null 说明是公共祖先,往上返回
if(left!=null && right!=null) return root;
//左空右不为空,继续把右子树的往上返回
else if(left == null && right!=null) return right;
else if(left != null && right == null) return left;
else return null;
  • 其实已经包含了第二种情况!遇到了自身是公共祖先的,就直接return root了,不去遍历下面的了!
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return root;
        if(root == p || root == q) return root;
        
        TreeNode left = lowestCommonAncestor(root.left,p,q); //相当于告诉我们左子树有没有出现过p q
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        //左右都不为null 说明是公共祖先,往上返回
        if(left!=null && right!=null) return root;
        //左空右不为空,继续把右子树的往上返回
        else if(left == null && right!=null) return right;
        else if(left != null && right == null) return left;
        else return null;
    }
}

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

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

相关文章

Spring高级面试题-2024

Spring 框架中都用到了哪些设计模式&#xff1f; 1. 简单工厂&#xff1a; ○ BeanFactory&#xff1a;Spring的BeanFactory充当工厂&#xff0c;负责根据配置信息创建Bean实例。它是一种工厂模式的应用&#xff0c;根据指定的类名或ID创建Bean对象。2. 工厂方法&#xff…

numcpp boostvs2017踩坑记录

之前想用boost1.69版本&#xff0c;但是boost与numcpp编译过程死活找不到boost1.69&#xff0c;踩坑无数&#xff0c;只能采用1.79版本。 https://www.cnblogs.com/tang-zhou-zhou/p/16067695.html 在 Windows 下通过 CMake 使用 Boost 库_cmake boost-CSDN博客 在VS2019中配…

析构 函数

对象死亡的时候会调用析构函数 #include<iostream> using namespace std;class MM { public:~MM(){cout << "调用析构函数" << endl << endl;}};int main() {{MM mm;//动态申请的内存需要手动释放MM* p new MM();cout << "1...…

【Java常用的API】JDK7以前时间相关类

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

js实现拖放效果

dataTransfer对象 说明&#xff1a;dataTransfer对象用于从被拖动元素向放置目标传递字符串数据。因为这个对象是 event 的属性&#xff0c;所以在拖放事件的事件处理程序外部无法访问 dataTransfer。在事件处理程序内部&#xff0c;可以使用这个对象的属性和方法实现拖放功能…

Linux(centos7)部署hadoop集群

部署环境要求:已完成JDK环境部署、配置完成固定IP、SSH免费登录、防火墙关闭等。 1、下载、上传主机 官网:https://hadoop.apache.org 2、解压缩、创建软连接 解压: tar -zxvf hadoop-3.3.6.tar.gz软连接: ln -s /usr/local/apps/hadoop-3.3.6 hadoop3、文件配置 hadoo…

合辑下载 | MatrixOne 与 MySQL 全面对比

前言 MatrixOne是一款高度兼容MySQL语法的HTAP数据库&#xff0c;采用云原生化和存储、计算、事务分离的架构打造了HSTAP超融合数据引擎&#xff0c;实现单一数据库系统同时支持OLTP、OLAP、流计算等多种业务负载。基于MatrixOne高度兼容MySQL的定位&#xff0c;社区的小伙伴在…

多层陶瓷电容器(MLCC)的基本结构与特点

多层陶瓷电容器&#xff08;MLCC&#xff09;是一种电子元件&#xff0c;用于存储电荷和调节电路中的电容值。它们由多个陶瓷层组成&#xff0c;每个层之间夹有金属电极&#xff0c;然后堆叠在一起&#xff0c;并在两端连接上导体引线&#xff0c;形成一个整体结构。在外部通常…

【保姆级讲解如何下载MATLAB和安装MATLAB】

&#x1f308;博主&#xff1a;程序员不想YY啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 &#x1f91d;希望本文对您有所裨益&#xff0c;如有…

【Java程序设计】【C00384】基于(JavaWeb)Springboot的民航网上订票系统(有论文)

【C00384】基于&#xff08;JavaWeb&#xff09;Springboot的民航网上订票系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#x…

Linux的VirtualBox中USB设备无法选择USB3.0怎么办?

在VirtualBox中&#xff0c;如果遇到USB设备无法选择 USB 3.0 的问题&#xff0c;可以尝试按照以下步骤来解决&#xff1a; 确保VirtualBox版本支持USB 3.0&#xff1a;首先&#xff0c;你需要确认你的VirtualBox版本是否支持USB 3.0。一些较旧的版本可能不支持&#xff0c;因此…

09 网络ARP请求,响应,ICMP协议

arp协议_arp请求_arp回应 ICMP包构造ping搜狐服务器参考 #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <string.h> #includ…

加密软件VMProtect教程:使用脚本Mach-O文件

VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic&#xff08;本机&#xff09;、Virtual Pascal和XCode编译器。 同时&#xff0c;VMProtect有一个内置的反汇编程序&#xff0c;可以与Windows和Mac OS X可执行文件一起…

怎么制作iOS证书

首先我们登录appuploder官网 搜索 appuploder 第一个就是我们官网啦&#xff0c;网址是&#xff1a;Appuploader home -- A tool improve ios develop efficiency such as submit ipa to appstore and manage ios certificate 可以跨平台开发&#xff0c;无论是Windows还是Ma…

前端面试题---->JavaScript

const声明的对象属性和数组的值可以被修改吗&#xff1f;为什么 原因&#xff1a;当使用const声明一个对象或数组时&#xff0c;实际上是保证了对象或数组的引用不会被修改&#xff0c;但对象或数组本身的属性或元素是可以被修改的。这是因为const只能保证指向的内存地址不变&a…

搭载前净柔泉女冲技术的科勒马桶盖,你的家中必备

近几年智能家居逐渐成为众多家庭的首选&#xff0c;尤其是智能马桶已经逐渐变成家中必备&#xff0c;但智能马桶动辄几千上万的价格让很多家庭望而却步&#xff0c;于是智能马桶盖应运而生。科勒清舒宝智能便盖不仅可以适配市面上大多数马桶&#xff0c;而且功能丰富&#xff0…

基于springboot+vue调用百度ai实现车牌号识别功能

百度车牌号识别官方文档 结果视频演示 后端代码 private String getCarNumber(String imagePath, int count) {// 请求urlString url "https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate";try {byte[] imgData FileUtil.readFileByBytes(imagePath);Stri…

精酿啤酒:多阶段发酵工艺的特点与优势

Fendi Club啤酒采用多阶段发酵工艺&#xff0c;这种工艺在啤酒酿造中具有显著的特点和优势。 首先&#xff0c;多阶段发酵工艺是一种复杂的酿造过程&#xff0c;它包括多个阶段的发酵和陈化过程。这种工艺需要切确控制每个阶段的时间、温度和酵母种类等参数&#xff0c;以确保…

【揭秘】企讯通106短信通知:那些你不可不知的“幕后功臣”

在日常生活中&#xff0c;你是否留意过那些来自“106”开头的短信&#xff1f;它们悄无声息地出现在你的手机收件箱&#xff0c;为你带来账单提醒、验证码、优惠活动等各类重要信息。看似平淡无奇的“106短信通知”&#xff0c;实则蕴含着丰富的科技力量与智慧结晶。今天&#…

together.ai简介

Together AI Solutions | Fastest Tools for Building Private Models for Enterprise Quickstart