华为OD机试 - 创建二叉树(Java 2024 E卷 200分)

题目描述

给定一系列树状结构操作的问题,通过 Q 次查询还原树结构并输出结果。题目要求实现一个类 Solution,其方法 recoverTree 需要根据输入的操作数组 operations 还原树的结构,并返回树的根节点。每个操作 operations[i] = [height, index] 表示在高度为 height 的位置插入一个索引为 index 的节点。

  • 树节点定义

    • 每个节点 node 存在左子节点,则初始为 null
    • 每个节点 node 存在右子节点,则初始为 null
    • 每个节点存储一个高度值 height 和索引值 index
  • 输入要求

    • heightindex 初始为 0,并按计数递增。
    • index 存储节点的创建顺序。
  • 注意事项

    • 输入用例保证每次操作对应的节点已经存在。
    • 控制台输出的内容是根据还原后的树根节点,按照层次遍历方式 Q 次查询打印的结果。

输入输出示例

示例 1:
输入: operations = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]
输出: [0, 0, 1, 1, 0]
解释:

  • [0, 0]:创建高度 0,索引 0 的节点,作为根节点。
  • [0, 1]:创建高度 0,索引 1 的节点,插入到根节点的左子树(因为高度相同,按索引顺序)。
  • [1, 1]:创建高度 1,索引 1 的节点,插入到根节点的右子树(高度更高)。
  • [1, 0]:创建高度 1,索引 0 的节点,插入到根节点的左子树(高度更高)。
  • [0, 0]:查询高度 0,索引 0 的节点,返回其值 0。

示例 2:
输入: operations = [[-1, 0], [1, 3], [null, 2]]
输出: [-1, 0, 1, 3, null, 2]
解释:

  • [-1, 0]:创建高度 -1,索引 0 的节点,作为根节点。
  • [1, 3]:创建高度 1,索引 3 的节点,插入到根节点的右子树(高度更高)。
  • [null, 2]:查询高度 null,索引 2 的节点,返回 null。

解题思路

问题分析

题目要求根据一系列操作还原一棵树,并通过查询返回指定节点的值。核心在于:

  1. 树的构建:根据 operations 数组中的 [height, index] 创建节点并插入树中。
  2. 插入规则:高度决定节点的层级,索引决定插入顺序。
  3. 查询操作:根据 [height, index] 找到对应节点并返回其值。
算法选择
  1. 树结构:使用二叉树结构存储节点,每个节点包含 heightindex,并有左右子节点。
  2. 插入规则
    • 如果高度相同,优先插入到左子树。
    • 如果高度更高,优先插入到右子树。
    • 如果高度更低,插入到左子树。
  3. 层次遍历:在查询时,通过层次遍历找到目标节点。
步骤详解
  1. 定义节点类:包含 heightindex、左子节点和右子节点。
  2. 构建树
    • 遍历 operations,对于每个操作:
      • 如果 height 不为 null,创建新节点并插入树中。
      • 插入时,比较 heightindex,决定插入到左子树还是右子树。
  3. 查询节点
    • 遍历 operations,对于查询操作(heightnull),通过层次遍历找到目标节点并返回其值。
  4. 返回结果:按照查询顺序返回结果数组。

代码实现

Java
class TreeNode {int height;int index;TreeNode left;TreeNode right;TreeNode(int height, int index) {this.height = height;this.index = index;this.left = null;this.right = null;}
}class Solution {public int[] recoverTree(int[][] operations) {TreeNode root = null;List<Integer> result = new ArrayList<>();// 构建树for (int[] op : operations) {int height = op[0];int index = op[1];// 如果 height 不为 null,插入节点if (height != Integer.MIN_VALUE) {TreeNode node = new TreeNode(height, index);if (root == null) {root = node;} else {insertNode(root, node);}}}// 查询节点for (int[] op : operations) {int height = op[0];int index = op[1];if (height == Integer.MIN_VALUE) {// 查询操作TreeNode target = findNode(root, index);if (target == null) {result.add(null);} else {result.add(target.height);}} else {result.add(height);}}// 转换为数组int[] res = new int[result.size()];for (int i = 0; i < result.size(); i++) {if (result.get(i) == null) {res[i] = Integer.MIN_VALUE; // 用 MIN_VALUE 表示 null} else {res[i] = result.get(i);}}return res;}private void insertNode(TreeNode root, TreeNode node) {TreeNode current = root;while (true) {if (node.height == current.height) {if (current.left == null) {current.left = node;break;} else {current = current.left;}} else if (node.height > current.height) {if (current.right == null) {current.right = node;break;} else {current = current.right;}} else {if (current.left == null) {current.left = node;break;} else {current = current.left;}}}}private TreeNode findNode(TreeNode root, int index) {if (root == null) return null;Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while (!queue.isEmpty()) {TreeNode node = queue.poll();if (node.index == index) return node;if (node.left != null) queue.offer(node.left);if (node.right != null) queue.offer(node.right);}return null;}
}
Python
class TreeNode:def __init__(self, height, index):self.height = heightself.index = indexself.left = Noneself.right = Noneclass Solution:def recoverTree(self, operations):root = Noneresult = []# 构建树for height, index in operations:if height is not None:node = TreeNode(height, index)if root is None:root = nodeelse:self.insert_node(root, node)# 查询节点for height, index in operations:if height is None:target = self.find_node(root, index)result.append(target.height if target else None)else:result.append(height)return resultdef insert_node(self, root, node):current = rootwhile True:if node.height == current.height:if current.left is None:current.left = nodebreakelse:current = current.leftelif node.height > current.height:if current.right is None:current.right = nodebreakelse:current = current.rightelse:if current.left is None:current.left = nodebreakelse:current = current.leftdef find_node(self, root, index):if not root:return Nonefrom collections import dequequeue = deque([root])while queue:node = queue.popleft()if node.index == index:return nodeif node.left:queue.append(node.left)if node.right:queue.append(node.right)return None
C++
#include <vector>
#include <queue>
using namespace std;class TreeNode {
public:int height;int index;TreeNode* left;TreeNode* right;TreeNode(int h, int idx) : height(h), index(idx), left(nullptr), right(nullptr) {}
};class Solution {
public:vector<int> recoverTree(vector<vector<int>>& operations) {TreeNode* root = nullptr;vector<int> result;// 构建树for (const auto& op : operations) {int height = op[0];int index = op[1];if (height != INT_MIN) {TreeNode* node = new TreeNode(height, index);if (!root) {root = node;} else {insertNode(root, node);}}}// 查询节点for (const auto& op : operations) {int height = op[0];int index = op[1];if (height == INT_MIN) {TreeNode* target = findNode(root, index);if (target) {result.push_back(target->height);} else {result.push_back(INT_MIN);}} else {result.push_back(height);}}return result;}private:void insertNode(TreeNode* root, TreeNode* node) {TreeNode* current = root;while (true) {if (node->height == current->height) {if (!current->left) {current->left = node;break;} else {current = current->left;}} else if (node->height > current->height) {if (!current->right) {current->right = node;break;} else {current = current->right;}} else {if (!current->left) {current->left = node;break;} else {current = current->left;}}}}TreeNode* findNode(TreeNode* root, int index) {if (!root) return nullptr;queue<TreeNode*> q;q.push(root);while (!q.empty()) {TreeNode* node = q.front();q.pop();if (node->index == index) return node;if (node->left) q.push(node->left);if (node->right) q.push(node->right);}return nullptr;}
};
JavaScript
class TreeNode {constructor(height, index) {this.height = height;this.index = index;this.left = null;this.right = null;}
}/*** @param {number[][]} operations* @return {number[]}*/
var recoverTree = function(operations) {let root = null;let result = [];// 构建树for (let [height, index] of operations) {if (height !== null) {let node = new TreeNode(height, index);if (!root) {root = node;} else {insertNode(root, node);}}}// 查询节点for (let [height, index] of operations) {if (height === null) {let target = findNode(root, index);result.push(target ? target.height : null);} else {result.push(height);}}return result;function insertNode(root, node) {let current = root;while (true) {if (node.height === current.height) {if (!current.left) {current.left = node;break;} else {current = current.left;}} else if (node.height > current.height) {if (!current.right) {current.right = node;break;} else {current = current.right;}} else {if (!current.left) {current.left = node;break;} else {current = current.left;}}}}function findNode(root, index) {if (!root) return null;let queue = [root];while (queue.length) {let node = queue.shift();if (node.index === index) return node;if (node.left) queue.push(node.left);if (node.right) queue.push(node.right);}return null;}
};

复杂度分析

  • 时间复杂度:O(Q * H),其中 Q 是操作次数,H 是树的高度。每次插入和查询都需要遍历树的深度,平均情况下为 O(log Q),最坏情况下(树退化为链)为 O(Q)。
  • 空间复杂度:O(Q)。树中最多有 Q 个节点,存储树和队列的空间为 O(Q)。

测试用例示例

测试用例 1:
输入: operations = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]
预期输出: [0, 0, 1, 1, 0]
解释: 按照操作构建树,最后查询高度 0,索引 0 的节点,返回 0。

测试用例 2:
输入: operations = [[-1, 0], [1, 3], [null, 2]]
预期输出: [-1, 0, 1, 3, null, 2]
解释: 构建树后,查询索引 2 的节点,未找到,返回 null。

测试用例 3:
输入: operations = [[0, 0], [1, 1], [null, 1]]
预期输出: [0, 0, 1, 1]
解释: 构建树后,查询索引 1 的节点,返回高度 1。

问题总结

本题是一个树结构的构建和查询问题,核心在于根据高度和索引的规则插入节点,并通过层次遍历查询目标节点。算法的关键点包括:

  1. 插入规则:高度决定插入方向,相同高度优先左子树。
  2. 查询效率:通过层次遍历查找目标节点。
  3. 边界处理:处理 null 查询和未找到节点的情况。

该算法适用于动态构建树并查询的场景,但在树退化为链时效率较低。可能的优化方向包括使用平衡树(如 AVL 树或红黑树)来降低树高,从而将时间复杂度优化到 O(Q * log Q)。在实际应用中,例如文件系统或组织结构管理,可以用类似方法动态构建和查询树结构。

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

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

相关文章

Vue3 + Element Plus 图片加载优化全攻略

如果对你有帮助&#xff0c;请帮忙点个赞 一、为什么需要优化图片加载&#xff1f; 在Web开发中&#xff0c;未优化的图片会导致&#xff1a; 首屏加载时间过长&#xff08;LCP指标恶化&#xff09; 不必要的带宽消耗 低端设备卡顿 用户流量浪费 Element Plus的<el-im…

Python 基础知识整理笔记

闹麻了&#xff0c;因为各种原因&#xff0c;现在需要重新回顾一下Python&#xff0c;话不多说&#xff0c;开始吧 1. Python是解释型语言 && Python与C代码执行过程的区别&#xff1a; &#xff08;1&#xff09;C 源码&#xff08;Source&#xff09;&#xff1a;C的…

Windows Server中的NTP服务器部署(NTP Srver Deployment in Windows Server)

构建稳定内网时间同步&#xff1a;Windows Server中的NTP服务器部署指南 服务简介 NTP&#xff08;Network Time Protocol&#xff09;服务器是用于同步计算机网络中各设备时间的服务器。它通过网络协议与标准时间源&#xff08;如原子钟、GPS系统等&#xff09;进行时间同步&…

Linux驱动开发实战之PCIE驱动(一)

以下是针对Linux下PCI设备驱动开发的详细步骤指南及示例代码&#xff0c;适合刚入门的小白逐步学习和实践&#xff1a; 一、开发环境准备 安装开发工具sudo apt install build-essential linux-headers-$(uname -r)创建项目目录mkdir pci_driver && cd pci_driver二、…

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 的自动配置:约定优于配置的设计美学

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、Spring…

SourceTree的安装与使用

SourceTree的安装与使用 一、前言 作为可视化Git管理工具&#xff0c;SourceTree可以避免我们使用命令进行常规的代码拉取&#xff0c;更新&#xff0c;合并等操作。 鼠标点点就可以完成代码管理的工作。所以强烈推荐可视化的工具。不过SourceTree还是有点bug&#xff0c;比…

JMeter 性能测试

Jmeter 用户手册 名词解释&#xff1a; RPS&#xff1a;每秒请求数-每秒向服务器发送多少请求数&#xff08;一个场景&#xff0c;系统面临多大的压力&#xff09; TPS&#xff1a;每秒事务数-每秒能够处理多少请求/事务数性能评价标准&#xff08;其中的一个核心指标&#x…

Go语言的负载均衡

Go语言的负载均衡 引言 在互联网快速发展的今天&#xff0c;服务器的压力越来越大。随着用户的增加&#xff0c;单一服务器很难满足所有请求&#xff0c;导致延迟增加&#xff0c;服务质量下降。负载均衡&#xff0c;作为一种重要的技术手段&#xff0c;能够有效地分散用户请…

【Mac 从 0 到 1 保姆级配置教程 09】09. 快速配置终端复用工具 tmux 和 oh-my-tmux

文章目录 1. 前言2. 安装 tmux3. 配置 tmux4. 安装 oh-my-tmux5. 最后6. 参考资料7. 系列教程 Mac 从 0 到 1 保姆级配置教程目录&#xff0c;点击即可跳转对应文章&#xff1a; 【Mac 从 0 到 1 保姆级配置教程 00】 - 教程说明 【Mac 从 0 到 1 保姆级配置教程 01】 - 安装无…

【每日学点HarmonyOS Next知识】屏幕参数、半模态相关、三集联动、只显示部分卡面,自定义绘制

1、HarmonyOS 需要 获取屏幕 xdpi 与 ydpi 数据&#xff1f; 可以通过display.getDefaultDisplaySync参考链接&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-display-V5 ohos.display (屏幕属性) &#xff1a;屏幕属性提供管理…

Java 大视界 -- 基于 Java 的大数据机器学习模型的迁移学习应用与实践(129)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

通义万相 2.1 与蓝耘智算平台的深度协同,挖掘 AIGC 无限潜力并释放巨大未来价值

我的个人主页 我的专栏&#xff1a; 人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01; 点赞&#x1f44d;收藏❤ 引言&#xff1a;AIGC 浪潮下的新机遇 在当今数字化飞速发展的时代&#xff0c;人工智能生成内容&…

【BERT和GPT的区别】

BERT采用完形填空&#xff08;Masked Language Modeling, MLM&#xff09;与GPT采用自回归生成&#xff08;Autoregressive Generation&#xff09;的差异&#xff0c;本质源于两者对语言建模的不同哲学导向与技术目标的根本分歧。这种选择不仅塑造了模型的架构特性&#xff0c…

Java实体类转JSON时如何避免null值变成“null“?

在Java开发中&#xff0c;实体类与JSON的转换是一个非常常见的需求。今天&#xff0c;我们要聊聊一个特别的重要但又常常被忽视的问题&#xff1a;当我们将Java实体类转换为JSON格式时&#xff0c;如何处理那些null值&#xff0c;避免它们在JSON中出现为字符串“null”呢&#…

五大基础算法——枚举算法

枚举算法 是一种通过遍历所有可能的解来寻找问题答案的算法思想。它通常用于解决那些解空间有限且可以直接列举所有可能情况的问题。以下是枚举算法的核心概念、适用场景、实现方法及经典例题&#xff1a; 一、核心概念 解空间 所有可能的解的集合。 遍历 通过循环或递归逐一检…

C语言高级学习之变量和内存分布

一.变量和内存分布 1.课程要求 2.技术层次 3.C语言标准 1.3.1 K&R C 起初&#xff0c;C语言没有官方标准。1978年由美国电话电报公司(AT&T&#xff09;贝尔实验室正式发表了C语言。布莱恩柯林汉&#xff08;Brian Kernighan&#xff09; 和 丹尼斯里奇&#xff08;D…

【004】deepseek本地化部署后,python的调用方式_#py

python调用本地deepseek 1 本地化部署deepseek2 python调用方式 1 本地化部署deepseek 已经有很多大佬们说了不少部署本地化部署deepseek的工作了&#xff0c;我就不过多重复了。 先安装Ollama软件&#xff0c;再通过Ollama获取deepseek的模型文件&#xff0c;大家根据电脑的配…

蓝桥杯学习-12递归

12递归 1.概述 2.几个递归模板 (1)求阶乘 int f(int n){ if(n 1) return 1; return f(n-1) * n; }(2)斐波拉契序列 int f(int n){ if(n 1 || n 2) return n; return f(n - 1) f(n - 2); }例题一-蓝桥5194 int f(int n){if(n 0) return 1;if(n % 2 0) return f(n / 2)…

Python----数据可视化(Pyecharts三:绘图二:涟漪散点图,K线图,漏斗图,雷达图,词云图,地图,柱状图折线图组合,时间线轮廓图)

1、涟漪特效散点图 from pyecharts.globals import SymbolType from pyecharts.charts import EffectScatter from pyecharts.faker import Faker from pyecharts import options as opts from pyecharts.globals import ThemeType # 绘制图表 es (EffectScatter(init_optsop…

自然语言处理预训练模型的研究综述

&#x1f4d5;参考&#xff1a;&#xff1a;2020-11-02,https://kns.cnki.net/kcms/detail/11.2127.tp.20201030.1952.017.html 主要是这篇文章的自己摘了点笔记。 预训练模型的深度学目标是如何使预训练好的模型处于良好的初始状态&#xff0c;在下游任务中达到更好的性能表现…