给定一个没有重复元素的数组,写出生成这个数组的MaxTree的函数

题目:

给定一个没有重复元素的数组arr,写出生成这个数组的MaxTree的 函数,要求如果数组长度为N,则时间复杂度为O(N)、额外空间复杂度 为O(N)

一个数组的MaxTree定义如下

数组必须没有重复元素。

● MaxTree是一棵二叉树,数组的每一个值对应一个二叉树节 点。

包括MaxTree树在内且在其中的每一棵子树上,值最大的节点 都是树的头

解题思路:

因为MaxTree要求每个子树的最大值都是根节点。对于任意一个节点,它的父节点必须是比它大的数,而且这个父节点还要尽可能小(这样才不会影响它成为局部子树的根)。同时,左右子树分别是该节点左右两侧小于它的数构成的子树。

我们可以利用每个元素左右两边第一个比它大的数来构建这棵树。具体方法如下:

1. 对于数组中的每一个元素,找出它左边第一个比它大的数和右边第一个比它大的数。

2. 然后,每个元素的父节点应该是它左右两边第一个比它大的数中较小的那个。如果选较大的那个,那么另一个方向就会存在比父节点更大的数,不符合MaxTree的定义;如果左右都没有比它大的数,那么它就是根节点。

步骤:

1. 使用单调栈(递减栈)来快速找到每个元素左右两边第一个比它大的数。 - 从左到右遍历:得到每个元素左边第一个比它大的数(如果左边没有,则为null)。 - 从右到左遍历:得到每个元素右边第一个比它大的数(如果右边没有,则为null)。

2. 构建节点:为数组中的每个元素创建一个节点。

3. 确定父节点: - 对于每个元素,比较其左边第一个比它大的数(记为leftGreater)和右边第一个比它大的数(记为rightGreater): - 如果leftGreater和rightGreater都不存在,则该节点为根节点。 - 如果只有一个存在,则该存在的节点就是父节点。 - 如果两个都存在,选择其中较小的那个作为父节点。

4. 连接节点:将当前节点作为其父节点的左孩子或右孩子(如果父节点的左孩子为空则放左孩子,否则放右孩子)

代码实现:

import java.util.Stack;public class MaxTreeBuilder {static class Node {int value;Node left;Node right;public Node(int value) {this.value = value;}}public static Node buildMaxTree(int[] arr) {if (arr == null || arr.length == 0) return null;int n = arr.length;// 存储左侧第一个比当前元素大的索引int[] leftGreater = new int[n];// 存储右侧第一个比当前元素大的索引int[] rightGreater = new int[n];// 初始化边界数组for (int i = 0; i < n; i++) {leftGreater[i] = -1;  // -1表示不存在rightGreater[i] = -1;}// 单调栈计算leftGreaterStack<Integer> stack = new Stack<>();for (int i = 0; i < n; i++) {while (!stack.isEmpty() && arr[stack.peek()] < arr[i]) {stack.pop();}if (!stack.isEmpty()) {leftGreater[i] = stack.peek();}stack.push(i);}// 清空栈并计算rightGreaterstack.clear();for (int i = n - 1; i >= 0; i--) {while (!stack.isEmpty() && arr[stack.peek()] < arr[i]) {stack.pop();}if (!stack.isEmpty()) {rightGreater[i] = stack.peek();}stack.push(i);}// 创建节点数组Node[] nodes = new Node[n];for (int i = 0; i < n; i++) {nodes[i] = new Node(arr[i]);}// 构建父节点关系Node root = null;for (int i = 0; i < n; i++) {int leftIndex = leftGreater[i];int rightIndex = rightGreater[i];// 确定父节点索引int parentIndex = -1;if (leftIndex == -1 && rightIndex == -1) {root = nodes[i];  // 根节点continue;} else if (leftIndex == -1) {parentIndex = rightIndex;} else if (rightIndex == -1) {parentIndex = leftIndex;} else {// 选择值较小的作为父节点parentIndex = (arr[leftIndex] < arr[rightIndex]) ? leftIndex : rightIndex;}// 连接节点if (i < parentIndex) {nodes[parentIndex].left = nodes[i];} else {nodes[parentIndex].right = nodes[i];}}return root;}// 打印树结构(前序遍历用于验证)public static void printTree(Node root) {if (root == null) return;System.out.print(root.value + " ");printTree(root.left);printTree(root.right);}public static void main(String[] args) {int[] arr = {3, 4, 5, 1, 2};Node root = buildMaxTree(arr);System.out.println("MaxTree 前序遍历:");printTree(root);// 预期结构:5(4(3, null), 2(1, null))// 前序遍历:5 4 3 2 1}
}

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

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

相关文章

iOS 抓包实战:时间戳偏差导致的数据同步异常排查记录

“这条数据不是我填的”“我的更新被覆盖了”“两个设备显示不一致”——这些是产品上线后最令人头疼的反馈。 最近我们在一次用户同步问题排查中&#xff0c;发现表面是“数据丢失”问题&#xff0c;实则是多端数据提交时间戳处理不一致&#xff0c;导致后台认为老数据为新&a…

一款支持多日志器、多级别、多落地方式的同异步日志系统

文章目录 简介项目特点项目实现基础功能模块实现文件操作以及日期时间获取日志等级日志信息描述 异步功能模块实现缓冲区实现异步线程实现 核心功能模块实现日志格式解析落地操作实现日志器实现 测试测试环境测试参数测试结果性能分析 附件 简介 在现代软件开发与系统运维领域…

加固笔记本在户外勘探行业的应用:探索与科技的融合

在自然资源勘探、地质调查、石油天然气开发、矿产资源测绘等户外勘探行业中&#xff0c;作业环境常常复杂多变&#xff1a;风沙漫天的戈壁、雨雪交加的山区、湿热潮湿的丛林&#xff0c;甚至是极寒与高温并存的极端气候条件。面对这些挑战&#xff0c;普通的办公设备早已无法胜…

MySQL 连接指定端口后,为什么实际仍是 3306?

文章目录 MySQL 连接指定端口后&#xff0c;为什么实际仍是 3306&#xff1f;问题现象复现原因分析没有指定 -h&#xff0c;默认走的是本地 Unix Socket多实例环境中未显式指定目标地址 正确的连接方法方法一&#xff1a;添加 -h 127.0.0.1方法二&#xff1a;添加 --protocolTC…

【Android当用户两次打断息屏操作后,屏幕将会在10分钟内无法熄灭并持续点亮(关闭Android13新增的dim功能)】

UndimDetectorWakeLock持锁导致屏幕不灭问题处理SOP 问题描述 在Android T版本中&#xff0c;系统新增了SCREEN_BRIGHT_WAKE_LOCK&#xff08;UndimDetectorWakeLock&#xff09;机制。当设备处于低亮度&#xff08;dim&#xff09;状态时&#xff0c;用户两次打断屏幕熄灭操…

Tailwind CSS自定义用法

文章目录 前言✅ 一、集成 Tailwind CSS 到 React 项目1. 安装依赖2. 配置 tailwind.config.js3. 创建全局样式文件&#xff08;如 src/index.css&#xff09;tailwind base;tailwind components;tailwind utilities; 4. 在 main.tsx 或 main.jsx 中引入样式 ✅ 二、自定义样式…

linux面试常考

常用指令 常见题

Spring Boot 2.2.6调用DeepSeek API并通过SSE将流式响应推送给前端的完整实现

1. 添加依赖 (pom.xml) <dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- SSE 支持 --><depe…

LM1117-ADJ 简单介绍

LM1117-ADJ是一款可调输出电压的低压差线性稳压器&#xff08;LDO&#xff09;&#xff0c;具有以下关键特性和应用要点&#xff1a; 核心特性 可调输出电压 通过外部分压电阻&#xff08;R1和R2&#xff09;调节输出电压&#xff0c;范围为1.25V至13.8V。输出电压公式&#…

知名流体控制解决方案供应商“永盛科技”与商派ShopeX达成B2B商城项目合作

2025年6月&#xff0c;全球知名的工业流体控制解决方案服务商——永盛科技&#xff08;股票&#xff1a;874497&#xff09;&#xff0c;与商派ShopeX正式达成B2B商城项目合作。 此次合作将共同推动永盛科技B2B业务的数字化变革&#xff0c;提高B2B业务运营效率&#xff0c;同…

jvm简单八股

1、jvm中内存分为那几个区域&#xff0c;1.7和1.8 jvm 中主要有 程序计数器、虚拟机栈、本地方法栈、堆、方法区、直接内存。 线程私有的有&#xff1a;程序计数器、虚拟机栈、本地方法栈 线程共有的有&#xff1a;堆、方法区、直接内存 堆空间又可以分为&#xff1a;新时代、…

contOS7安装docker命令及yum源更换为国内源

docker介绍 Docker是一个开源的容器化平台,通过将应用程序及其依赖打包成轻量级、可移植的容器,确保开发、测试和部署环境的一致性。Docker的核心概念包括容器、镜像、Dockerfile和镜像仓库。容器是轻量级的虚拟化技术,共享宿主机内核但保持独立运行环境,启动快且资源占用少…

SpringBoot集成Redis-6.x版本流程

SpringBoot集成Redis是我们常见的功能&#xff0c;今天我们分享一下&#xff1a; 前言&#xff1a; 1、pom包引用 <!-- Redis Starter (默认使用 Lettuce) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boo…

zookeeper Curator(3):Watch事件监听

文章目录 Curator API 常用操作 Watch事件监听NodeCachePathChildrenCacheTreeCache 本章代码已分享至Gitee: https://gitee.com/lengcz/curator01 Curator API 常用操作 Watch事件监听 zookeeper 允许用户在指定节点上注册一些Watcher &#xff0c;并且在一些特定事件触发的时…

多模态融合相机L3CAM

多模态融合相机L3CAM L3CAM是Beamagine公司推出的多模态传感器融合技术&#xff0c;结合了激光雷达&#xff08;LiDAR&#xff09;和可见光摄像头&#xff0c;旨在为自动驾驶、工业机器人和其他需要精确环境感知的应用场景提供高效、安全的解决方案。 L3CAM技术参数 L3CAM结合…

结构化思维

前言 洞悉分析方法论 系统解决管理问题 1 构建问题分析框架 1.1 摘要 &#xff08;1&#xff09;何谓问题分析和解决&#xff1f; &#xff08;2&#xff09;问题分析和解决的基本原则 1.2 什么是问题分析与决策&#xff1f; 1.3 问题解决者需要具备的四种能力 &#xf…

什么是数字签名(ECDSA)?

数字签名是区块链、数字身份认证和安全通信的核心技术之一&#xff0c;ECDSA&#xff08;椭圆曲线数字签名算法&#xff09;是目前最常见、最主流的数字签名算法之一&#xff0c;尤其在区块链系统&#xff08;如比特币、以太坊、EOS&#xff09;中广泛应用。 一、什么是数字签名…

深入剖析AI大模型:Dify的介绍

今天介绍的内容&#xff0c;跟大模型开发还是息息相关的。俗话说&#xff1a;有人的地方就是江湖&#xff01;对于我们技术其实也一样&#xff0c;一个新技术的出现&#xff0c;自然会衍生出相应的生态圈。今天的文字只是介绍&#xff0c;以后会有专门的实操篇&#xff0c;主要…

Open VSX Registry关键漏洞使攻击者可完全控制Visual Studio Code扩展市场

网络安全研究人员近日披露了 Open VSX Registry&#xff08;"open-vsx[.]org"&#xff09;中存在的一个关键漏洞。若被成功利用&#xff0c;攻击者可能完全控制整个 Visual Studio Code 扩展市场&#xff0c;造成严重的供应链风险。 漏洞详情与潜在影响 Koi Securi…

Python从入门到高手9.1节-Python中的字典类型

目录 9.1.1 理解字典类型 9.1.2 字典的类型名 9.1.3 字典的定义 9.1.4 字典的主要性质 9.1.5 好好学习&#xff0c;天天向上 9.1.1 理解字典类型 在日常生活中&#xff0c;我们常常会接触到“字典”这种数据类型&#xff0c;例如一本书籍的目录结构&#xff0c;在目录结构…