夜雨聆风学习资料网

ARTICLE · 1039899

京东9月19日机考笔试题与解析

京东9月19日机考笔试题与解析

写在前面

本次给大家带来2026年9月19日京东笔试题的2道题,本场机考题目可在咱们平台上在线刷题。

大厂笔试AI Coding练习:CodeFun2000.com/aicoder-gym

题号
题目
难度(对标leetcode)
核心做法
1
风控排序评估
简单
排序
2
四因子乘积对
中等
数论

第1题-风控排序评估

题目内容

风控侧要对一批交易做欺诈打分。每笔交易有真实标签  表示正常, 表示欺诈)以及模型给出的风险分 (越大越像欺诈)。

请按 Mann-Whitney U 的秩统计来评估这批打分的排序质量,也就是 AUC。分数相同的交易必须用平均名次,不能随便拆开。

规则如下:

  1. 平均名次:把  笔交易按  从小到大排。名次从  起。若连续若干笔分数相同,占住第  到第  个位置,则它们的名次都取 
  2. 由正类名次和还原 AUC:记欺诈笔数为 ,正常笔数为 ,欺诈样本的名次之和为 。令

题解

解题思路

AUC 可以不画 ROC,直接用秩统计算。把每笔交易按风险分从小到大排,名次从  起。分数相同的几笔不能拆开,它们合占第  到第  个位置,每笔都记平均名次 

  1. 排序后扫一遍,把同分区间扩满,再把区间内所有下标写成同一个平均名次。
  2. 记欺诈笔数为 ,正常笔数为 ,欺诈样本的名次之和为 。若欺诈全部排在最前面,名次和最小是 。多出来的部分  就是正类“赢过”负类的对数(并列计 )。
  3. 一共有  对正负样本,因此 。输出必须保留  位小数。
  4. 常见假解:并列时按出现顺序硬拆成 ;名次从  起;按分数从大到小编号却仍套同一公式;只统计严格大于、并列不算 

复杂度分析

  • 时间复杂度:,主要花在按分数排序。,即使用  两两比较也对。
  • 空间复杂度:

代码实现

python代码(C++和JAVA代码见在线OJ网址)

defauc_from_ranks(labels, scores):"""    标签 1 为欺诈,0 为正常。分数越大越像欺诈。    并列分数占用一段名次区间,区间内每笔都取左右端点的均值。    """    m = len(labels)# 按下标稳定排序,保证同分时相对顺序确定    order = sorted(range(m), key=lambda i: scores[i])    rank = [0.0] * m    i = 0while i < m:        j = i# 向右扩到同一分数的最后一笔while j + 1 < m and scores[order[j + 1]] == scores[order[i]]:            j += 1# 名次从 1 起,区间 [i+1, j+1]        avg = (i + 1 + j + 1) / 2.0for k in range(i, j + 1):            rank[order[k]] = avg        i = j + 1    k_pos = 0    s_pos = 0.0for i in range(m):if labels[i] == 1:            k_pos += 1            s_pos += rank[i]    k_neg = m - k_pos# U 统计量:正类名次和减去「全排在最前」时的最小名次和    u = s_pos - k_pos * (k_pos + 1) / 2.0return u / (k_pos * k_neg)defmain():# 四级协议:第一行笔数,第二行标签,第三行风险分    m = int(input())    labels = list(map(int, input().split()))    scores = list(map(float, input().split()))    auc = auc_from_ranks(labels, scores)    print("{:.6f}".format(auc))if __name__ == "__main__":    main()

第2题-四因子乘积对

题目内容

边缘集群里排着  个推理批次,第  个批次带着指纹 。调度会从中任取两个不同批次做成一组,把两个指纹相乘,若乘积的正因子恰好有  个,就记这组为合法组。

同一对批次只算一次,顺序无关。请统计合法组的个数。

题解

解题思路

一个正整数恰好有四个正因子,当且仅当它是某个质数的立方 (因子 ),或两个不同质数之积 (因子 )。

因此两个指纹  合法,只有下面几类:

  1.  或  乘上质数只有两个因子,不能配质数。
  2. 两个不同的质数 。相同质数乘出来是平方,只有三个因子。
  3. ,乘积恰好 

其余形态( 配  配 、合数配合数等)乘积的因子都会多于或少于四个。做法:

  1. 筛出  的最小质因子,把每个  拆成质因子。
  2. 统计  的个数、 与  的个数、每个质数出现次数、每个  出现次数。
  3. 答案为 ,其中  是质数形态的总个数, 分别是  与  的出现次数。

复杂度分析

  • 时间复杂度:。筛最小质因子 ,每个指纹按最小质因子拆分。
  • 空间复杂度:。主要是筛数组

代码实现

python代码(C++和JAVA代码见在线OJ网址)

MAXB = 1000000defbuild_spf():# 线性筛最小质因子,后面拆指纹用    spf = list(range(MAXB + 1))    i = 2while i * i <= MAXB:if spf[i] == i:            j = i * iwhile j <= MAXB:if spf[j] == j:                    spf[j] = i                j += i        i += 1return spfdefcount_pairs(vals):    spf = build_spf()    cnt1 = 0    special = 0    prime_cnt = {}    square_cnt = {}for x in vals:if x == 1:# 1 只能和 p^3 或 p*q 配对            cnt1 += 1continue        n = x        factors = []while n > 1:            p = spf[n]            c = 0while n % p == 0:                n //= p                c += 1            factors.append((p, c))if len(factors) == 1:            p, c = factors[0]if c == 1:                prime_cnt[p] = prime_cnt.get(p, 0) + 1elif c == 2:                square_cnt[p] = square_cnt.get(p, 0) + 1elif c == 3:                special += 1elif len(factors) == 2and factors[0][1] == 1and factors[1][1] == 1:# 两个不同质数之积            special += 1# 1 与「恰好四因子」的数    ans = cnt1 * special    total_p = 0for p, c in prime_cnt.items():        total_p += c# 同一个质数两次乘起来是平方,因子个数不是 4        ans -= c * (c - 1) // 2# p 与 p^2 乘积是 p^3        ans += c * square_cnt.get(p, 0)# 不同质数两两配对    ans += total_p * (total_p - 1) // 2return ansdefmain():# 一行:先 m 再跟 m 个指纹    parts = list(map(int, input().split()))    m = parts[0]    vals = parts[1 : 1 + m]    print(count_pairs(vals))if __name__ == "__main__":    main()

相关学习资料