华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
请按下列描述构建一颗二叉树 Q,并返回该树的根节点:
1、先创建值为 0 的根结点,根节点 Q 在第 0 层;
2、然后根据 operations 依次添加节点:operations[i] = [height, index] 表示对第 height 层的第 index 个节点 node,添加值为 i 的子节点:
- 若 node 无【左子节点】,则添加;
- 若 node 有【左子节点】但是没有【右子节点】,则添加右子节点;
- 若无可添加的子节点,则返回错误。
height, index 均为 0 开始计数; index 依存于节点的创建顺序。
注意:
- 输入用例保证每次操作对应的节点已存在;
- 控制台输出的内容是根据返回的树根节点,按层序遍历 Q 二叉树打印的结果。
二、输入描述
operations
三、输出描述
根据返回的树根节点,按照层序遍历 Q 二叉树打印的结果
备注
1 <= operations.length <= 100
operations[i].length == 2
0 <= operations[i][0] < 100
0 <= operations[i][1] < 100
四、测试用例
1、输入
[[0, 0], [0, 0], [1, 1], [1, 0], [0, 0]]
2、输出
[-1, 0, 1, 3, null, 2]
3、说明
首个值是根节点的值,也是返回值;
null 表示是空节点,此特殊层序遍历会遍历有值节点的 null 子节点
五、解题思路
1、问题分析
给定一系列操作,每个操作由两个整数 [height, index] 组成,表示在二叉树的第 height 层的第 index 个节点上添加一个子节点,子节点的值为操作的顺序索引 i。具体添加规则如下:
- 如果目标节点没有左子节点,则添加为左子节点。
- 如果目标节点已有左子节点但没有右子节点,则添加为右子节点。
- 如果目标节点的左右子节点都已存在,则返回错误(但题目保证输入操作都是有效的,可以添加节点)。
构建完二叉树后,进行层序遍历(广度优先遍历),并按照题目要求输出结果,空缺的节点用 null 表示。
2、具体步骤
- 初始化根节点:
- 创建根节点,值为 -1(根据测试用例)。
- 将根节点放入一个列表中,表示第0层。
- 构建树的层级结构:
- 使用一个二维列表 treeLevels,其中 treeLevels[h] 表示第 h 层的所有节点。
- 初始时,treeLevels[0] 只包含根节点。
- 处理每个操作:
- 遍历每个操作 [height, index]。
- 根据 height 和 index 找到目标父节点 parentNode。
- 创建一个新的子节点,值为当前操作的索引 i。
- 根据父节点的现有子节点情况,添加为左子节点或右子节点,并将新节点添加到 treeLevels[h + 1] 中对应层。
- 层序遍历:
- 使用队列进行广度优先遍历。
- 遍历过程中记录每个节点的值,如果节点为空,则记录 null。
- 最后移除结果列表末尾多余的 null 值。
- 输出结果:
- 将结果列表转换为字符串形式,按照题目要求的格式输出。
六、Python算法源码
import sys
import json
from collections import deque
# 定义二叉树的节点结构
class Node:
def __init__(self, value):
self.value = value # 节点的值
self.left = None # 左子节点
self.right = None # 右子节点
def build_binary_tree(operations):
# 初始化根节点,值为 -1
root = Node(-1)
# 使用列表存储每一层的节点,tree_levels[h] 表示第 h 层的节点列表
tree_levels = []
tree_levels.append([root]) # 第0层只有根节点
# 遍历每个操作,依次添加节点
for i, operation in enumerate(operations):
height, index = operation # 获取操作的高度和索引
# 如果当前层级的列表不足以包含目标高度的下一层,则添加新的层
while len(tree_levels) <= height + 1:
tree_levels.append([])
# 获取目标父节点
parent_node = tree_levels[height][index]
# 创建新的子节点,值为操作的索引 i
child_node = Node(i)
# 如果父节点没有左子节点,则添加为左子节点
if parent_node.left is None:
parent_node.left = child_node
# 否则,如果父节点没有右子节点,则添加为右子节点
elif parent_node.right is None:
parent_node.right = child_node
else:
# 按题目保证,这种情况不会发生
raise Exception("父节点的左右子节点都已存在,无法添加新的子节点")
# 将新节点添加到对应层级的列表中
tree_levels[height + 1].append(child_node)
# 进行层序遍历,记录节点值
result = []
queue = deque()
queue.append(root) # 从根节点开始
while queue:
current_node = queue.popleft() # 取出队首节点
if current_node is not None:
result.append(current_node.value) # 记录节点的值
queue.append(current_node.left) # 添加左子节点到队列
queue.append(current_node.right) # 添加右子节点到队列
else:
result.append(None) # 记录为空节点
# 移除结果列表末尾的多余 None 值
while result and result[-1] is None:
result.pop()
# 将结果列表转换为字符串格式
result_str = '[' + ', '.join(['null' if x is None else str(x) for x in result]) + ']'
return result_str
def main():
# 读取标准输入中的一行字符串
input_line = sys.stdin.readline().strip()
# 解析输入字符串为二维整数数组
operations = json.loads(input_line)
# 构建二叉树并获取层序遍历结果
output = build_binary_tree(operations)
# 输出结果
print(output)
if __name__ == "__main__":
main()
七、JavaScript算法源码
// 定义二叉树的节点结构
class Node {
constructor(value) {
this.value = value; // 节点的值
this.left = null; // 左子节点
this.right = null; // 右子节点
}
}
// 构建二叉树并返回层序遍历结果的字符串表示
function buildBinaryTree(operations) {
// 初始化根节点,值为 -1
const root = new Node(-1);
// 使用数组存储每一层的节点,treeLevels[h] 表示第 h 层的节点列表
const treeLevels = [];
treeLevels.push([root]); // 第0层只有根节点
// 遍历每个操作,依次添加节点
operations.forEach((operation, i) => {
const height = operation[0]; // 获取操作的高度
const index = operation[1]; // 获取操作的索引
// 如果当前层级的列表不足以包含目标高度的下一层,则添加新的层
while (treeLevels.length <= height + 1) {
treeLevels.push([]);
}
// 获取目标父节点
const parentNode = treeLevels[height][index];
// 创建新的子节点,值为操作的索引 i
const childNode = new Node(i);
// 如果父节点没有左子节点,则添加为左子节点
if (parentNode.left === null) {
parentNode.left = childNode;
}
// 否则,如果父节点没有右子节点,则添加为右子节点
else if (parentNode.right === null) {
parentNode.right = childNode;
}
else {
// 按题目保证,这种情况不会发生
throw new Error("父节点的左右子节点都已存在,无法添加新的子节点");
}
// 将新节点添加到对应层级的列表中
treeLevels[height + 1].push(childNode);
});
// 进行层序遍历,记录节点值
const result = [];
const queue = [];
queue.push(root); // 从根节点开始
while (queue.length > 0) {
const currentNode = queue.shift(); // 取出队首节点
if (currentNode !== null) {
result.push(currentNode.value); // 记录节点的值
queue.push(currentNode.left); // 添加左子节点到队列
queue.push(currentNode.right); // 添加右子节点到队列
}
else {
result.push(null); // 记录为空节点
}
}
// 移除结果数组末尾的多余 null 值
while (result.length > 0 && result[result.length - 1] === null) {
result.pop();
}
// 将结果数组转换为字符串格式
const resultStr = '[' + result.map(x => x === null ? 'null' : x.toString()).join(', ') + ']';
return resultStr;
}
// 主函数,读取输入并输出结果
function main() {
const fs = require('fs');
const input = fs.readFileSync('/dev/stdin', 'utf8').trim();
// 解析输入字符串为二维整数数组
const operations = JSON.parse(input);
// 构建二叉树并获取层序遍历结果
const output = buildBinaryTree(operations);
// 输出结果
console.log(output);
}
main();
八、C算法源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义二叉树的节点结构
typedef struct Node {
int value; // 节点的值
struct Node* left; // 左子节点
struct Node* right; // 右子节点
} Node;
// 创建新的节点
Node* createNode(int value) {
Node* newNode = (Node*)malloc(sizeof(Node)); // 分配内存
newNode->value = value; // 设置节点值
newNode->left = NULL; // 初始化左子节点为空
newNode->right = NULL; // 初始化右子节点为空
return newNode; // 返回新节点
}
// 动态数组结构,用于存储每一层的节点
typedef struct {
Node*** levels; // 二维指针,levels[h][i] 表示第 h 层的第 i 个节点
int* counts; // 每一层的节点数量
int capacity; // 当前层数
} TreeLevels;
// 初始化 TreeLevels 结构
TreeLevels* initTreeLevels(int initial_capacity) {
TreeLevels* tl = (TreeLevels*)malloc(sizeof(TreeLevels));
tl->levels = (Node***)malloc(sizeof(Node**) * initial_capacity);
tl->counts = (int*)malloc(sizeof(int) * initial_capacity);
for(int i = 0; i < initial_capacity; i++) {
tl->levels[i] = NULL;
tl->counts[i] = 0;
}
tl->capacity = initial_capacity;
return tl;
}
// 添加节点到指定层
void addNodeToLevel(TreeLevels* tl, int level, Node* node) {
if(level >= tl->capacity) {
// 扩展层级容量
tl->levels = (Node***)realloc(tl->levels, sizeof(Node**) * (level + 1));
tl->counts = (int*)realloc(tl->counts, sizeof(int) * (level + 1));
for(int i = tl->capacity; i <= level; i++) {
tl->levels[i] = NULL;
tl->counts[i] = 0;
}
tl->capacity = level + 1;
}
// 添加节点到指定层
tl->levels[level] = (Node**)realloc(tl->levels[level], sizeof(Node*) * (tl->counts[level] + 1));
tl->levels[level][tl->counts[level]] = node;
tl->counts[level]++;
}
// 层序遍历并获取结果字符串
char* levelOrderTraversal(Node* root) {
// 使用动态数组模拟队列
Node** queue = (Node**)malloc(sizeof(Node*) * 1000);
int front = 0, rear = 0;
// 结果数组,初始化为全零
int* result = (int*)malloc(sizeof(int) * 1000);
int result_size = 0;
int null_marker = 1001; // 特殊标记,表示 null
// 入队根节点
queue[rear++] = root;
while(front < rear) {
Node* current = queue[front++];
if(current != NULL) {
result[result_size++] = current->value;
queue[rear++] = current->left;
queue[rear++] = current->right;
}
else {
result[result_size++] = null_marker;
}
}
// 移除结果末尾的 null
while(result_size > 0 && result[result_size - 1] == null_marker) {
result_size--;
}
// 构建结果字符串
char* res_str = (char*)malloc(sizeof(char) * 5000);
strcpy(res_str, "[");
for(int i = 0; i < result_size; i++) {
if(result[i] == null_marker) {
strcat(res_str, "null");
}
else {
char num_str[12];
sprintf(num_str, "%d", result[i]);
strcat(res_str, num_str);
}
if(i != result_size -1) {
strcat(res_str, ", ");
}
}
strcat(res_str, "]");
// 释放内存
free(queue);
free(result);
return res_str;
}
int main() {
// 读取输入
char input_line[1000];
fgets(input_line, sizeof(input_line), stdin);
// 解析输入,假设输入格式为 [[0,0], [0,0], [1,1], [1,0], [0,0]]
// 先统计操作数量
int operations[100][2];
int op_count = 0;
char* token = strtok(input_line, "[] ,");
while(token != NULL) {
operations[op_count][op_count %2] = atoi(token);
op_count++;
token = strtok(token, "[] ,");
}
op_count /=2;
// 转换为二维数组
int num_operations = op_count;
int ops[100][2];
for(int i = 0; i < num_operations; i++) {
ops[i][0] = operations[2*i][0];
ops[i][1] = operations[2*i +1][0];
}
// 初始化根节点
Node* root = createNode(-1);
// 初始化 TreeLevels 结构
TreeLevels* tree_levels = initTreeLevels(10);
addNodeToLevel(tree_levels, 0, root); // 第0层添加根节点
// 处理每个操作
for(int i = 0; i < num_operations; i++) {
int height = ops[i][0];
int index = ops[i][1];
// 获取父节点
Node* parent = tree_levels->levels[height][index];
// 创建子节点
Node* child = createNode(i);
// 添加子节点
if(parent->left == NULL) {
parent->left = child;
}
else if(parent->right == NULL) {
parent->right = child;
}
else {
// 根据题目保证,不会发生
printf("Error: 父节点的左右子节点都已存在。\n");
return 1;
}
// 添加子节点到下一层
addNodeToLevel(tree_levels, height +1, child);
}
// 进行层序遍历并获取结果
char* output = levelOrderTraversal(root);
// 输出结果
printf("%s\n", output);
// 释放内存
free(output);
// 此处省略其他内存释放,为简化代码
return 0;
}
九、C++算法源码
#include <bits/stdc++.h>
using namespace std;
// 定义二叉树的节点结构
struct Node {
int value; // 节点的值
Node* left; // 左子节点
Node* right; // 右子节点
Node(int val) : value(val), left(nullptr), right(nullptr) {}
};
// 构建二叉树并返回层序遍历结果的字符串表示
string buildBinaryTree(vector<vector<int>> operations) {
// 初始化根节点,值为 -1
Node* root = new Node(-1);
// 使用vector存储每一层的节点,treeLevels[h] 表示第 h 层的节点列表
vector<vector<Node*>> treeLevels;
treeLevels.emplace_back(); // 添加第0层
treeLevels[0].push_back(root); // 第0层只有根节点
// 遍历每个操作,依次添加节点
for(int i = 0; i < operations.size(); i++) {
int height = operations[i][0]; // 获取操作的高度
int index = operations[i][1]; // 获取操作的索引
// 如果当前层级的列表不足以包含目标高度的下一层,则添加新的层
while(treeLevels.size() <= height + 1) {
treeLevels.emplace_back();
}
// 获取目标父节点
Node* parentNode = treeLevels[height][index];
// 创建新的子节点,值为操作的索引 i
Node* childNode = new Node(i);
// 如果父节点没有左子节点,则添加为左子节点
if(parentNode->left == nullptr) {
parentNode->left = childNode;
}
// 否则,如果父节点没有右子节点,则添加为右子节点
else if(parentNode->right == nullptr) {
parentNode->right = childNode;
}
else {
// 根据题目保证,不会发生
throw runtime_error("父节点的左右子节点都已存在,无法添加新的子节点");
}
// 将新节点添加到对应层级的列表中
treeLevels[height + 1].push_back(childNode);
}
// 进行层序遍历,记录节点值
vector<string> result;
queue<Node*> q;
q.push(root); // 从根节点开始
while(!q.empty()) {
Node* current = q.front();
q.pop();
if(current != nullptr) {
result.push_back(to_string(current->value)); // 记录节点的值
q.push(current->left); // 添加左子节点到队列
q.push(current->right); // 添加右子节点到队列
}
else {
result.push_back("null"); // 记录为空节点
}
}
// 移除结果末尾的多余 "null" 值
while(!result.empty() && result.back() == "null") {
result.pop_back();
}
// 构建结果字符串
string res_str = "[";
for(int i = 0; i < result.size(); i++) {
res_str += result[i];
if(i != result.size() -1) {
res_str += ", ";
}
}
res_str += "]";
return res_str;
}
int main(){
// 读取输入
string input_line;
getline(cin, input_line);
// 解析输入字符串为二维整数数组
// 使用字符串流和手动解析
vector<vector<int>> operations;
int num;
vector<int> current_op;
for(char c : input_line){
if(c == '['){
current_op.clear();
}
else if(c == ',' || c == ']'){
if(!current_op.empty()){
operations.emplace_back(current_op);
current_op.clear();
}
}
else if(isdigit(c) || c == '-'){
string num_str;
while(isdigit(c) || c == '-'){
num_str += c;
// 读取下一个字符
size_t pos = input_line.find(c);
if(pos == string::npos || pos +1 >= input_line.size()) break;
c = input_line[pos +1];
}
current_op.push_back(stoi(num_str));
}
}
// 构建二叉树并获取层序遍历结果
string output = buildBinaryTree(operations);
// 输出结果
cout << output << endl;
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。