通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
KNN 分类 · 对应本题的思路、过程和代码
给定 n 个带标签的样本和 m 个查询点,对每个查询点:计算它到每个样本的平方欧氏距离(不做开方,特征为整数,距离为精确整数),取距离最小的 k 个样本作为近邻;距离相同时样本编号(输入顺序,从 0 开始)小者优先。在 k 个近邻的标签中做多数表决,票数相同时类别编号小者当选。输出每个查询点的预测类别。
这类题属于算法机考高频题型中「华为 AI 岗 / 排序」方向的高频题型,通常考察对「华为 AI 岗 / 排序」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入 n d k m,分别为样本数、特征维数、近邻数和查询数。接下来 n 行,每行 d 个整数特征和一个整数标签。随后 m 行,每行 d 个整数,表示查询点。
输出 m 行,每行一个整数,表示对应查询点的预测类别。
1 <= n <= 2000;1 <= d <= 8;1 <= k <= n;1 <= m <= 200;整数特征绝对值不超过 10000;0 <= 标签 <= 100。
示例 1
输入示例
5 2 3 2 0 0 0 1 0 0 5 5 1 6 5 1 0 1 0 0 0 5 4
输出示例
0 1
三近邻多数表决。
示例 2
输入示例
3 1 1 1 -2 5 2 9 4 9 0
输出示例
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
5
到 -2 和 2 距离都是 4,取样本编号更小的 0 号,类别 5。
时间限制 2000 ms · 内存限制 256 MB
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有
这些是真正决定能不能 AC、但通用题解里常被略过的点。
对每个查询点,计算它与所有训练样本的平方欧氏距离。不开方既不改变距离顺序,也能保持整数比较。把样本表示为 (distance, index, label),按距离升序、编号升序排序后取前 k 个。随后统计这些近邻的标签次数,选择票数最多的类别;票数相同时选择类别编号更小者。
平方根在非负区间严格单调,所以按平方距离排序与按欧氏距离排序结果相同。排序的第二关键字准确处理等距样本。前 k 个元素因此就是题目定义的近邻集合;标签选择再按“票数降序、类别升序”比较,得到唯一的预测类别。
每个查询计算距离需要 O(nd),全排序需要 O(n log n),总时间为 O(m(nd+n log n));保存距离列表需要 O(n) 空间。平方距离使用 64 位整数。
样本编号从 0 开始;等距时必须使用输入编号裁决。k=n 时全部样本参与投票,标签平票仍取更小类别。
# 整数平方距离(不开方,精确比较),近邻按 (距离,编号) 排序取前 k;
# 表决键=(−票数,类别),两级并列都取小;C++/Java 距离用 64 位。
import sys
def solve() -> None:
data = sys.stdin.buffer.read().split()
if not data:
return
it = iter(data)
n, d, k, m = (int(next(it)) for _ in range(4))
x, y = [], []
for _ in range(n):
x.append([int(next(it)) for _ in range(d)])
y.append(int(next(it)))
queries = [[int(next(it)) for _ in range(d)] for _ in range(m)]
out = []
for q in queries:
order = []
for idx, row in enumerate(x):
dist = 0
for j in range(d):
diff = row[j] - q[j]
dist += diff * diff
order.append((dist, idx))
order.sort()
votes = {}
for dist, idx in order[:k]:
votes[y[idx]] = votes.get(y[idx], 0) + 1
best_label = -1
best_count = -1
for label, count in votes.items():
if count > best_count or (count == best_count and label < best_label):
best_label = label
best_count = count
out.append(str(best_label))
print("\n".join(out))
if __name__ == "__main__":
solve()