通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
决策树推理 · 对应本题的思路、过程和代码
给定若干棵二叉决策树和一批样本,请模拟树模型推理。内部节点根据某个特征是否小于等于阈值决定走左子树或右子树;叶子节点给出类别。每棵树得到一个类别后,用多数表决得到最终结果;如果多个类别票数相同,选择数值更小的类别。
这类题属于算法机考高频题型中「华为 AI 岗 / 决策树」方向的高频题型,通常考察对「华为 AI 岗 / 决策树」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入 T d q,表示树的数量、特征维度和待预测样本数。随后对每棵树,先输入节点数 s,再输入 s 行节点。节点编号从 1 开始,1 号为根。叶子节点格式为 L label;内部节点格式为 N feature threshold left right。最后输入 q 行样本,每行 d 个特征值。
输出 q 行,每行一个整数,表示对应样本的最终类别。
1 <= T <= 20;1 <= d <= 20;所有树的节点总数不超过 5000;1 <= q <= 2000;特征值和阈值绝对值不超过 100000。
示例 1
输入示例
1 1 3 3 N 1 5 2 3 L 0 L 1 3 5 6
输出示例
0 0 1
单棵树基础推理
示例 2
输入示例
3 2 3 3 N 1 5 2 3 L 0 L 1 3 N 2 0 2 3 L 1 L 2 3 N 1 2 2 3 L 0 L 2 1 -1 6 1 3 5
输出示例
0 2 2
多棵树多数表决
时间限制 3000 ms · 内存限制 256 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
这些是真正决定能不能 AC、但通用题解里常被略过的点。
每棵树用节点编号索引保存。从 1 号根节点开始循环:内部节点读取指定特征,若特征值小于等于阈值则转到左孩子,否则转到右孩子;到达叶节点后取得该树的类别。对所有树的结果计票,选择票数最多的类别,平票时选择数值更小的类别。
循环在每个内部节点都执行题面规定的唯一分支,因此最终到达的叶节点就是该树对样本的预测。对 T 棵树分别求值后,计票覆盖了全部预测;按“票数降序、类别升序”选择,准确实现多数表决与平票规则。
设最大树深为 h,每个样本遍历 T 棵树,时间复杂度为 O(qTh)。节点表占 O(S) 空间,其中 S 为全部树的节点总数;单个样本计票最多占 O(T)。
阈值相等时走左子树。树可能退化成很深的链,使用循环可避免递归深度限制。类别编号不要求连续,应使用映射计票。
# 多树推理:循环走树(深树递归会栈溢出),小于等于阈值走左;
# 多棵树表决取票数最多,平票取数值更小的类别,键=(−票数,类别)。
import sys
from collections import defaultdict
def solve() -> None:
data = sys.stdin.buffer.read().split()
if not data:
return
at = 0
t = int(data[at]); at += 1
d = int(data[at]); at += 1
q = int(data[at]); at += 1
trees = []
for _ in range(t):
s = int(data[at]); at += 1
nodes = [None] * (s + 1)
for i in range(1, s + 1):
typ = data[at].decode(); at += 1
if typ == "L":
nodes[i] = ("L", int(data[at])); at += 1
else:
feature = int(data[at]) - 1; at += 1
threshold = float(data[at]); at += 1
left = int(data[at]); at += 1
right = int(data[at]); at += 1
nodes[i] = ("N", feature, threshold, left, right)
trees.append(nodes)
ans = []
for _ in range(q):
x = [float(data[at + i]) for i in range(d)]
at += d
votes = defaultdict(int)
for nodes in trees:
cur = 1
while nodes[cur][0] != "L":
_, feature, threshold, left, right = nodes[cur]
cur = left if x[feature] <= threshold else right
votes[nodes[cur][1]] += 1
ans.append(str(min(votes, key=lambda label: (-votes[label], label))))
print("\n".join(ans))
if __name__ == "__main__":
solve()