算法训练营 day21 二叉树 二叉搜索树的最小绝对差 二叉搜索树中的众数 二叉树的最近公共祖先

news2024/12/24 9:16:06

算法训练营 day21 二叉树 二叉搜索树的最小绝对差 二叉搜索树中的众数 二叉树的最近公共祖先

二叉搜索树的最小绝对差

530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

递归法

注意是二叉搜索树,二叉搜索树可是有序的。

遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。在一个有序数组上求两个数最小差值。

需要用一个pre节点记录一下cur节点的前一个节点。

在这里插入图片描述

//一般解法
class Solution {
    ArrayList<Integer> arr = new ArrayList<>();

    public int getMinimumDifference(TreeNode root) {
        traversal(root);
        if (arr.size() < 2) return 0;
        int result = Integer.MAX_VALUE;
        for (int i = 1; i < arr.size(); i++) {
            result = Math.min(result, arr.get(i) - arr.get(i - 1));
        }
        return result;
    }

    private void traversal(TreeNode root) {
        if (root == null) return;
        traversal(root.left);
        arr.add(root.val);
        traversal(root.right);
    }
}

//双指针递归
class Solution {
    int result = Integer.MAX_VALUE;
    TreeNode pre = null;

    public int getMinimumDifference(TreeNode root) {
        traversal(root);
        return result;
    }
    private void traversal(TreeNode cur) {
        if (cur == null) return;
        traversal(cur.left);
        if (pre != null) {
            result = Math.min(result, cur.val - pre.val);
        }
        pre = cur;
        traversal(cur.right);
    }
}

迭代法

class Solution {
    public int getMinimumDifference(TreeNode root) {
        Stack<TreeNode> st = new Stack<TreeNode>();
        int result = Integer.MAX_VALUE;
        TreeNode pre = null;
        if (root == null) return 0;
        st.push(root);
        while (!st.isEmpty()) {
            TreeNode node = st.pop();
            if (node != null) {
                if (node.right != null) st.push(node.right);
                st.push(node);
                st.push(null);
                if (node.left != null) st.push(node.left);
            } else {
                node = st.pop();
                if (pre != null) {
                    result = Math.min(result, node.val - pre.val);
                }
                pre = node;
            }
        } 
        return result;
    }
}

二叉搜索树中的众数

501. 二叉搜索树中的众数 - 力扣(LeetCode)

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

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

假定 BST 满足如下定义:

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

既然是搜索树,它中序遍历就是有序的

遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。

递归法

class Solution {
    ArrayList<Integer> resultList = new ArrayList<>();;
    TreeNode pre = null;
    int maxCount = 0;
    int count = 0;

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

    private 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) resultList.add(cur.val);
        if (count > maxCount) {
            maxCount = count;
            resultList.clear();
            resultList.add(cur.val);
        }
        traversal(cur.right);
    }
}

迭代法

class Solution {
    public int[] findMode(TreeNode root) {
        ArrayList<Integer> resultList = new ArrayList<>();
        TreeNode pre = null;
        int maxCount = 0;
        int count = 0;
        Stack<TreeNode> st = new Stack<>();
        if (root == null) return new int[0];
        st.push(root);


        while (!st.isEmpty()) {
            TreeNode node = st.pop();
            if (node != null) {
                if (node.right != null) st.push(node.right);
                st.push(node);
                st.push(null);
                if (node.left != null) st.push(node.left);
            } else {
                node = st.pop();
                if (pre == null || pre.val != node.val) count = 1;
                else count++;
                pre = node;
                if (count == maxCount) resultList.add(node.val);
                if (count > maxCount) {
                    maxCount = count;
                    resultList.clear();
                    resultList.add(node.val);
                }
            }
        }

        int[] result = new int[resultList.size()];
        for (int i = 0; i < resultList.size(); i++) {
            result[i] = resultList.get(i);
        }
        return result;
    }
}

二叉树的最近公共祖先

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

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

首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。 即情况一:

在这里插入图片描述

二叉树节点数值是不重复的,而且一定存在 q 和 p

但是很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q§。 情况二:

在这里插入图片描述

递归三部曲:

  • 确定递归函数返回值以及参数

需要递归函数返回值,来告诉我们是否找到节点q或者p,那么返回值为bool类型就可以了。

但我们还要返回最近公共节点,可以利用上题目中返回值是TreeNode * ,那么如果遇到p或者q,就把q或者p返回,返回值不为空,就说明找到了q或者p。

  • 确定终止条件

遇到空的话,因为树都是空了,所以返回空。

那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到,

  • 确定单层递归逻辑

值得注意的是 本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) return null;
        if (root == q || root == p) return root;

        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        if (left!=null&&right!=null)return root;
        
        if (left==null&&right!=null) return right;
        else if (left!=null&&right==null) return left;
        else return null;
    }
}

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

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

相关文章

《啊哈算法》第四章之深度优先搜索

✌好听的歌一起分享&#xff01; 稻香 (女声版) - 余不不 - 单曲 - 网易云音乐 目录 模板 例子 1&#xff0c;关于遍历 2&#xff0c;关于边界 正文 1&#xff0c;概念 2&#xff0c;解救小哈 例子源码和题目 1&#xff0c;小学奥数 2&#xff0c;全排列 3&#x…

【自学Docker 】Docker inspect命令

Docker inspect命令 大纲 docker inspect教程 使用 docker inspect 命令可以用来获取 Docker容器 或者 Docker镜像 的元数据。该命令后面的 CONTAINER 可以是容器Id&#xff0c;或者是容器名。 docker inspect语法 haicoder(www.haicoder.net)# docker inspect [OPTIONS] N…

python小知识

一、pip config list -v#pip在哪里寻找pip.conf文件 阿里云镜像&#xff1a; 二、安装anaconda(阿里云镜像库) 1、安装完成&#xff0c;命令行输入&#xff1a;conda config生成.condarc文件&#xff08;运行期配置文件&#xff09; 2、如果原本的源中的源地址是 https&…

webService速通教学(送源码)

什么是WebService webService是一种古老的互联网通讯方法。通过http通讯&#xff0c;将数据封装成XML的形式在网络中传输。习惯Java开发的伙伴肯定会对其嗤之以鼻&#xff0c;为什么不用Json传输&#xff0c;为什么不直接通过url拼参数&#xff1f;最大的两个因素是&#xff1…

Nginx基础03:配置文件nginx.conf(Part2)

上一篇文章概述与罗列了"全局配置块、events配置块、http全局块"的基本配置与属性&#xff0c;本篇文章将继续深入server块的配置项&#xff0c;以及相关应用。上篇文章地址&#xff1a;Nginx基础02&#xff1a;配置文件nginx.conf&#xff08;Part1&#xff09;如何…

从“工业报国为己任”到“科技创造优质生活”——华阳集团三十周年记

2022年10月28日&#xff0c;ADAYO华阳集团(002906.SZ)发布了一份“亮眼”的三季报。2022年1-9月公司实现营业收入40.08亿元&#xff0c;同比增长28.03%&#xff0c;实现归母净利润2.67亿元&#xff0c;同比增长28.28%。其中第三季度营业收入、净利润绝对值均为上市以来单季度最…

Android 深入系统完全讲解(23)

OpenGL 和 OpenGLES 简介 OpenGL(Open Graphics Library)意为开放图形库&#xff0c;是一个跨平台的图形 API&#xff0c;用于指定 3D 图 形处理硬件中的软硬件编程接口。OpenGL 一般用于图形工作站&#xff0c;PC 端使用。由于性能和可 移植性等各方面原因&#xff0c;在移动端…

分享72个PHP源码,总有一款适合您

PHP源码 分享72个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 72个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/11BEwLdHiZF0DqB3Bhb3FaQ?pwdjoxq 提取码&#xff…

使用docker搭建版本控制系统-SVN

作者简介&#xff1a;一名Linux运维工程师&#xff0c;主要分享自己遇到的学习过程与遇到的问题。 座右铭&#xff1a;选择时尽心&#xff0c;行动时尽力&#xff0c;坚持时无怨&#xff0c;结束时无悔。 个人公众号&#xff1a;早九晚十二&#xff0c;欢迎大家留言交流…

day41|● 343. 整数拆分 ● 96.不同的二叉搜索树

题目链接:343. 整数拆分 1.代码 暴力做法&#xff1a;n前进行组合搜索得出二维数组result存放结果&#xff0c;然后对里面的元素进行乘积&#xff0c;谁最大就是结果 2.递归做法 class Solution { public:int integerBreak(int n) {vector<int>f(n 5, 0);f[2] 1;for …

LinkedList链表知识点概括

作者&#xff1a;爱塔居的博客_CSDN博客-JavaSE,数据结构领域博主 专栏&#xff1a;数据结构 作者简介&#xff1a;大三学生&#xff0c;希望2023年迎来更优秀的自己&#xff01;希望跟大家一同进步~ 文章目录 前言 一、链表的基本概念 二、面试题实战 前言 顺序表/ArrayList:…

数据湖之Hudi基础:核心原理

继续Hudi核心概念 参考官网描述与尚硅谷hudi公开资料 文章目录基本概念时间轴TimeLine1.Instants action 在表上执行的操作类型2.Instant time3.State两个时间概念文件布局&#xff08;FileLayout&#xff09;索引 Index表类型&#xff08;Table Types&#xff09;Copy On Writ…

echarts:实现3D地图版块叠加动效散点效果

需求描述 如下图所示&#xff0c;展示3D效果的地图版块&#xff0c;并叠加显示动效散点&#xff1a; 实现思路 首先是3D地图版块效果的实现&#xff0c;可以参考广州3D地图&#xff1b;而动效散点的实现&#xff0c;可以参考地图发散分布。 这里再提一个经过尝试并不行的思…

【mmdeploy】mmseg转ONNX/TensorRT,附推理代码

目录 1.关于mmdeploy 2.环境安装 2.1预编译安装&#xff08;Linux-x86_64, CUDA 11.x, TensorRT 8.2.3.0&#xff09;&#xff1a; 2.2预编译安装&#xff08;Linux-x86_64, CUDA 11.x, ONNX&#xff09;&#xff1a; 3.mmseg工程torch转onnx 4.使用onnx模型文件进行推理…

Dubbo框架学习(第一章Dubbo简介)

由于在微服务领域有两大框架统治&#xff0c;一个是springCloud的全家桶&#xff0c;一个是Dubbo。我用Dubbo比较少&#xff0c;所以也是学习状态。Dubbo框架学习&#xff0c;资料来源于cn.dubbo.apache.org。第一章Dubbo简介Apache Dubbo 是一款 RPC 微服务框架&#xff0c;提…

字节跳动青训营--前端day2

文章目录前言一、css1. css的组成2. css三种使用方式3.css的工作方式二、 css选择器Selector1. 选择元素的方式2. 伪类&#xff08;pseudo-classes&#xff09;2.1 状态伪类2.1 结构伪类3.通过组合选择元素3.1 直接组合3.2 元素组合的拓展4. 选择器的特异度&#xff08;Specifi…

小型水库雨水情测报和安全监测解决方案

平升电子小型水库雨水情测报和安全监测解决方案辅助水利管理部门实现水库雨水情信息“全要素、全量程、全覆盖”自动测报。系统具备水库水位、雨量、现场图像/视频等水文信息采集、传输、处理及预警广播等功能&#xff0c;有效提升了雨水情信息的时效性和准确度&#xff0c;为保…

jmeter 使用beanshell 编写脚本

一、介绍 1.1 介绍 BeanShell是一个小型的、免费的、可嵌入使用Java编写的具有对象脚本语言特性的Java源码解释器。 动态执行所有Java语句、Java代码片段以及弱类型Java和附加的脚本的便利 透明地访问所有Java对象和API 四种运行模式&#xff1a;命令行、控制台、Applet、远…

数据结构专题 -- 哈希思想详解

代码会存放在&#xff1a; https://github.com/sjmshsh/Data-Struct-HandWriting 通过阅读本篇文章&#xff0c;你可以学到&#xff1a; 哈希思想及其本质使用C实现简易的哈希表哈希思想的应用 位图布隆过滤器哈希切分极致升华&#xff0c;海量数据处理面试题 拓展 – 一致性…

二叉树的应用——哈夫曼树

哈夫曼树与哈夫曼编码 1.树的带权路径长 百分制成绩转五级制的算法流程图&#xff08;A/B/C/D/E的人数分别为6/18/21/36/19&#xff09;带权路径长 路经长 x 权重 树的带权路经长&#xff1a;所有叶结点的带权路径长度之和。 例如&#xff1a; &#xff08;a&#xff09;图…