华为OD统一考试B卷 | 200分】数组二叉树 ( C++ Java JavaScript )
题目描述
二叉树也可以用数组来存储,给定一个数组,树的根节点的值存储在下标1,对于存储在下标N的节点,他的左子节点和右子节点分别存储在下标2*N
和2*N+1
,并且我们用值-1代表一个节点为空。
给定一个数组存储的二叉树,试求从根节点到最小的叶子节点的路径,路径由节点的值组成。
输入描述
输入一行为数组的内容,数组的每个元素都是正整数,元素间用空格分割。
注意第一个元素即为根节点的值,即数组的第N
个元素对应下标N
,下标0
在树的表示中没有使用,所以我们省略了。
输入的树最多为7层。
输出描述
输出从根节点到最小叶子节点的路径上,各个节点的值,由空格分割,用例保证最小叶子节点只有一个。
用例
输入 | 3 5 7 -1 -1 2 4 |
---|---|
输出 | 3 7 2 |
说明 | 最小叶子节点的路径为3 7 2 |
输入 | 5 9 8 -1 -1 7 -1 -1 -1 -1 -1 6 |
---|---|
输出 | 5 8 7 6 |
说明 | 最小叶子节点的路径为5 8 7 6 ,注意数组仅存储至最后一个非空节点,故不包含节点"7"右子节点的-1 |
Java
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (input) => {
const arr = input.split(' ').map(Number);
const n = arr.length - 1;
let min = Infinity;
let minIdx = -1;
for (let i = n; i >= 1; i--) {
if (arr[i] !== -1) {
if (i * 2 + 1 <= n && arr[i * 2 + 1] !== -1) continue;
if (i * 2 + 2 <= n && arr[i * 2 + 2] !== -1) continue;
if (min > arr[i]) {
min = arr[i];
minIdx = i;
}
}
}
const path = [];
path.unshift(min);
while (minIdx !== 0) {
const f = Math.floor((minIdx - 1) / 2);
path.unshift(arr[f]);
minIdx = f;
}
console.log(path.join(' '));
});
C++
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
string input;
getline(cin, input);
stringstream ss(input);
vector<int> arr;
int num;
while (ss >> num) {
arr.push_back(num);
}
int n = arr.size() - 1;
int min = INT_MAX;
int minIdx = -1;
for (int i = n; i >= 1; i--) {
if (arr[i] != -1) {
if (i * 2 + 1 <= n && arr[i * 2 + 1] != -1) continue;
if (i * 2 + 2 <= n && arr[i * 2 + 2] != -1) continue;
if (min > arr[i]) {
min = arr[i];
minIdx = i;
}
}
}
vector<int> path;
path.push_back(min);
while (minIdx != 0) {
int f = (minIdx - 1) / 2;
path.push_back(arr[f]);
minIdx = f;
}
reverse(path.begin(), path.end());
for (int i = 0; i < path.size(); i++) {
cout << path[i] << " ";
}
cout << endl;
return 0;
}
Javascript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (input) => {
const arr = input.split(' ').map(Number);
const n = arr.length - 1;
let min = Infinity;
let minIdx = -1;
for (let i = n; i >= 1; i--) {
if (arr[i] !== -1) {
if (i * 2 + 1 <= n && arr[i * 2 + 1] !== -1) continue;
if (i * 2 + 2 <= n && arr[i * 2 + 2] !== -1) continue;
if (min > arr[i]) {
min = arr[i];
minIdx = i;
}
}
}
const path = [];
path.unshift(min);
while (minIdx !== 0) {
const f = Math.floor((minIdx - 1) / 2);
path.unshift(arr[f]);
minIdx = f;
}
console.log(path.join(' '));
});
python
import queue
# 读入数组
arr = list(map(int, input().split()))
n = len(arr) - 1 # 数组长度
min_val = float('inf') # 记录最小值
min_idx = -1 # 记录最小值的下标
# 从后往前遍历数组
for i in range(n, 0, -1):
if arr[i] != -1: # 当前节点不为空
# 如果有左子节点或右子节点,说明不是叶子节点,跳过
if i * 2 + 1 <= n and arr[i * 2 + 1] != -1:
continue
if i * 2 + 2 <= n and arr[i * 2 + 2] != -1:
continue
# 更新最小值和最小值下标
if min_val > arr[i]:
min_val = arr[i]
min_idx = i
# 构造路径
path = queue.deque()
path.appendleft(min_val)
while min_idx != 0: # 从叶子节点往根节点遍历
f = (min_idx - 1) // 2 # 父节点下标
path.appendleft(arr[f]) # 将父节点加入路径
min_idx = f # 更新最小值下标
# 输出结果
print(' '.join(map(str, path)))