当前位置: 首页 > web >正文

给定一个没有重复元素的数组,写出生成这个数组的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.xdnf.cn/news/14798.html

相关文章:

  • TDengine 如何使用 MQTT 采集数据?
  • lambda、function基础/响应式编程基础
  • [论文阅读] 软件工程 | 微前端在电商领域的实践:一项案例研究的深度解析
  • NLP中的同义词替换及我踩的坑
  • 创客匠人视角:创始人 IP 打造为何成为知识变现的核心竞争力
  • 【算法深练】单调栈:有序入栈,及时删除垃圾数据
  • 鸿蒙5:组件监听和部分状态管理V2
  • 为何需要防爆平板?它究竟有何能耐?
  • 【龙泽科技】新能源汽车故障诊断仿真教学软件【吉利几何G6】
  • 学习使用dotnet-dump工具分析.net内存转储文件(2)
  • vue-28(服务器端渲染(SSR)简介及其优势)
  • 舵机在不同类型机器人中的应用
  • Python 数据分析与可视化 Day 10 - 数据合并与连接
  • Linux的top指令CPU占用率详解(白话版)——Linux进阶常用知识点
  • 网络缓冲区
  • uni-app项目实战笔记26--uniapp实现富文本展示
  • 展开说说:Android之ContentProvider源码浅析
  • 机器学习算法-K近邻算法-KNN
  • Linux tcp_info:监控TCP连接的秘密武器
  • Day44 预训练模型
  • OpenCV图像添加水印
  • Python 数据分析与可视化 Day 9 - 缺失值与异常值处理技巧
  • 秘窟燃战.纷魄凌霄(第二集)
  • Re:从零开始的文件分配方式(考研向)
  • 深入浅出Java NIO:原理、实战与性能优化
  • FPGA在嵌入式图像处理中的深度应用!
  • Springboot多用户博客管理系统的设计与实现0ce8q(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 【大数据】大数据产品基础篇
  • 微信小程序:实现树形结构组件
  • 用 pnpm + TurboRepo,构建多项目高效开发体系