通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
分类阈值与 F1 · 对应本题的思路、过程和代码
给定 n 个样本的模型分数和真实标签。选择一个阈值 theta,当 score >= theta 时预测为正类,否则预测为负类。阈值只能取某个样本分数。记 TP、FP、FN 分别为真阳性、假阳性、假阴性,本题使用 F1 = 2 * TP / (2 * TP + FP + FN);如果分母为 0,则 F1 定义为 0。请找出 F1 值最大的阈值;如果多个阈值的 F1 相同,选择数值更大的阈值。
这类题属于算法机考高频题型中「华为 AI 岗 / 排序」方向的高频题型,通常考察对「华为 AI 岗 / 排序」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入整数 n。接下来 n 行,每行输入一个实数 score 和一个整数 label,label 只可能为 0 或 1。
输出一行,包含最优阈值和对应 F1。阈值保留四位小数,F1 保留六位小数。
1 <= n <= 50000;score 的绝对值不超过 100000;测试数据保证最优阈值不落在四位小数的舍入中点。
示例 1
输入示例
4 0.9 1 0.8 0 0.7 1 0.4 0
输出示例
0.7000 0.800000
基础阈值选择
示例 2
输入示例
4 0.8 1 0.8 0 0.5 1 0.2 0
输出示例
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
0.5000 0.800000
相同分数必须一起跨过阈值
时间限制 3000 ms · 内存限制 256 MB
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有
这些是真正决定能不能 AC、但通用题解里常被略过的点。
按分数从高到低排序,并按相同分数分组。阈值下降到某一组分数时,把整组样本加入“预测为正”的集合:正标签增加 TP,负标签增加 FP,FN 等于正样本总数减 TP。每处理完一整组,再计算该阈值的 F1。若 F1 更大则更新答案;F1 相同时保留更大的阈值。
阈值只能取样本分数。当阈值等于 s 时,所有分数大于等于 s 的样本都预测为正,因此相同分数必须同时改变状态。扫描到每个分数组结束时,TP、FP、FN 恰好对应这一候选阈值。枚举全部不同分数后取最优值即得到全局最优阈值。
排序需要 O(n log n),分组扫描需要 O(n);保存样本需要 O(n) 空间。
F1 分母为 0 时按题意取 0。相同分数不能逐个评估;从高分向低分扫描时,只在 F1 严格增大时更新,就能在并列时保留更大的阈值。
# 按分数从高到低排序,同分整组一起跨线,增量维护 TP/FP(FN=正样本总数−TP);
# 每档算 F1=2TP/(2TP+FP+FN),严格大于才更新——并列自然保留更大阈值。
import sys
def solve() -> None:
data = sys.stdin.buffer.read().split()
if not data:
return
n = int(data[0])
items = []
at = 1
for _ in range(n):
score = float(data[at]); at += 1
label = int(data[at]); at += 1
items.append((score, label))
items.sort(reverse=True)
total_pos = sum(label for _, label in items)
tp = fp = 0
best_f1 = -1.0
best_threshold = items[0][0]
i = 0
while i < n:
score = items[i][0]
while i < n and items[i][0] == score:
if items[i][1] == 1:
tp += 1
else:
fp += 1
i += 1
fn = total_pos - tp
denom = 2 * tp + fp + fn
f1 = 0.0 if denom == 0 else (2 * tp) / denom
if f1 > best_f1 + 1e-12 or (abs(f1 - best_f1) <= 1e-12 and score > best_threshold):
best_f1 = f1
best_threshold = score
print(f"{best_threshold:.4f} {best_f1:.6f}")
if __name__ == "__main__":
solve()