下面进行华为2026年6月24日AI岗机考题的复盘和关键知识点(重点)深度剖析,笔者今天(7月7日)刷完选择题和2道算法题。选择题考到机器学习基础理论、线性代数、多模态对齐、LLM推理配置等知识点。编程题还是传统的数据结构与算法的考点,一个是基础的模拟(深度学习,Transformer的RoPE场景)的题目(评级中等),一个是AI Infra模型量化场景问题(二分法DP,评级困难)。
说明:文章内选择题证明和论述部分的绿色字体是AI生成内容,红色字体是人工增添或重要修改内容。
目录
选择题(用时):40分钟
第一题
束搜索,正确答案A。

Beam Search的算法流程:
- 对当前的 B 个候选句子,分别计算词典里所有 token 的概率。
- 生成
(V 为词表大小)个候选新句子。 - 在这海量候选中,挑选出整体序列概率最高的 B 个,作为下一步的输入。
关于束搜索和Top_K的区别:Top-k 选的是当前步概率最高的 k 个单个 token(然后随机抽一个);而 Beam Search 选的是整个序列(从开头到当前词)概率最高的 B 个完整路径。它不是在"服务"某个单步的 token 筛选,而是在为整个句子做全局规划。
第四题
跨模态对齐,正确答案C。

| 特性 | 对比损失 (Contrastive Loss) | 匹配损失 (Matching Loss) |
|---|---|---|
| 核心目标 | 度量学习:学习一个判别性的嵌入空间,让匹配的样本对靠近,不匹配的远离。 | 相关性判断:学习一个评分函数,直接判断一对样本是否匹配,是一个二分类问题。 |
| 输入形式 | 通常接收成对的输入(如图文对),并利用批次内的负样本进行对比。 | 输入是一个样本对(如一张图和一段文字),输出一个预测类别(同类或者不同类)。 |
| 训练信号 | 相对的。一个正样本对的相似度要高于所有负样本对。 | 绝对的。为匹配的正样本对打高分(如1),为不匹配的负样本对打低分(如0)。 |
| 典型损失函数 | InfoNCE Loss、Triplet Loss、NT-Xent Loss。 | Binary Cross-Entropy Loss (BCE)、Ranking Loss。 |
| 核心能力 | 表征对齐:将不同模态的数据映射到同一个语义空间,使其可直接比较。 | 关系建模:深入理解两个输入之间的语义关联程度。 |
以"图像-文本匹配"为例,假设有图像 I
和文本 T
:
- 对比损失:模型会这样学习:"I_猫 应该和 T_猫 在空间里靠近,同时要远离 T_狗、T_车 等。"它通过这种"拉近正例,推开负例"的方式,塑造了整个特征空间的几何结构。
- 匹配损失:模型学习一个二分类器,直接对 (I_猫, T_猫) 这个组合输出"匹配",对 (I_猫, T_狗) 输出"不匹配"。
OpenAI团队提出的CLIP(Contrastive Language-Image Pretraining
)图像-文本对比预训练模型就是基于对比损失训练了一个高质量的图文多模态共享语义空间。使用对比损失利用批次内的负样本,一次前向传播能处理N个正例和N×(N-1)个负例,计算效率高于匹配损失的批次样本对处理,大家可以理解成1对1和1对多,所以对比损失训练计算效率更高,也更适合处理多模态对齐任务
第十题
PCA主成分分析+方差贡献率,正确答案D。
计算均值和协方差矩阵,通过矩阵酉对角化分解,对角矩阵对角线上的元素自动就是方差(酉矩阵的基向量的模长(L2范数)是1),所以直接加和就可以,不需要再进行平方计算。

代码题1(中等)
用时21分钟,b2计算的指数项里面D/(D-2)借助AI Debug。
应用场景:Dynamic NTK-aware Scaled Rotational Position Encoding
注意:题目没有交代旋转基本单元pair的排列方式,需要读者有相关先验知识,也就是(0,1),(2,3),(4,5),(2*i,2*i+1)这种组合,步长为2,这一点在
的计算公式里也可以体现。

python
def code1():
import math
T, L, D, b, m = map(float, input().split())
b2 = b * (max(1, T / L) ** (D / (D - 2)))
x = list(map(float, input().split()))
x2 = x[:]
up = int(D // 2 - 1)
for i in range(0, up + 1):
ceta_mi = m * (b2 ** (-2 * i / D))
x[2 * i] = x2[2 * i] * math.cos(ceta_mi) - x2[2 * i + 1] * math.sin(ceta_mi)
x[2 * i + 1] = x2[2 * i] * math.sin(ceta_mi) + x2[2 * i + 1] * math.cos(ceta_mi)
for e in x:
print("{:.4f}".format(e), end=" ")
下面补充一下RoPE作为位置编码的独特优势以及Transformer位置编码常用的三种方式(表格):
- 天然具备相对位置建模能力:与将位置信息直接加到词向量上的传统方法不同,RoPE是在注意力机制内部,通过旋转查询(Query)和键(Key)向量来注入位置信息。这使得注意力分数的计算天然依赖于两个token之间的相对距离,这更符合语言理解的核心逻辑:我们关心的是词与词之间的距离,而非它们的绝对位置。
- 卓越的长度外推能力:这是RoPE被众多大模型(如LLaMA、ChatGLM)采用的关键原因。传统绝对位置编码受限于训练时的最大长度,而RoPE通过旋转矩阵编码相对位置,理论上可以扩展到任意长的序列。实验表明,在长序列任务上,RoPE的困惑度(Perplexity)上升远低于传统方案,在未见过的超长序列上的表现也显著更优。
- 更低的存储开销:RoPE由于不依赖可学习的位置参数,节省了存储开销。
- 具备远程衰减特性:RoPE使得两个token的注意力分数会随着它们之间相对距离的增加而衰减。这符合直觉:距离越远的词,对当前词的影响通常越小,这种 inductive bias 有助于模型更好地聚焦于局部上下文。
- 更强的泛化能力:RoPE的泛化能力在实际数据中得到了验证。在WikiText-103数据集上的对比实验中,RoPE方案的零样本外推能力达到了78%,远超绝对位置编码(12%)和相对位置编码(34%)。
| 位置编码类型 | 额外引入的计算复杂度 | 备注 |
|---|---|---|
| 绝对位置编码(正弦波/可学习) | ![]() |
仅在输入层做一次加法,之后注意力计算零额外开销。你判断得完全正确,这是 O(n)。 |
| 经典相对位置编码(Transformer-XL) | ![]() |
需要计算或查找 的位置偏置并加到注意力分数上。 |
| RoPE(旋转位置编码) | ![]() |
在计算 时进行旋转,之后注意力计算零额外开销。 |
代码题2(困难)
用时:N小时(超长),DeepSeek辅助

python
# 基于常规二维DP,时间复杂度N^2
def code2():
import sys
input=sys.stdin.readline
N, K = map(int, input().split())
a = list(map(int, input().split()))
import time
start=time.time()
cost = [[0 for i in range(N+1)] for j in range(N)]
prefix = [0 for i in range(N + 1)]
# 计算累加数组
for i in range(N):
prefix[i + 1] = prefix[i] + a[i]
# 使用累加数组计算cost函数
def cal_cost(l, r, med):
left_c = a[med] * (med - l) - (prefix[med] - prefix[l])
right_c = prefix[r + 1] - prefix[med + 1] - a[med] * (r - med)
return left_c + right_c
# 预存储cost
for i in range(N):
for j in range(i, N):
cost[i][j+1] = cal_cost(i, j, (i + j) // 2)
# 二维动态规划
INF = 10 ** 18
dp = [[INF for i in range(K + 1)] for j in range(N+1)]
# dp[1] = [0 for i in range(K + 1)]
# dp[0]=[0 for i in range(K+1)]
dp[0][0]=0
for k in range(1, K + 1):
for i in range(k, N+1):
for j in range(k-1, i):
dp[i][k] = min(dp[i][k], dp[j][k - 1] + cost[j][i])
# print(f"Cost({j},{i}):",cost[j][i])
# print(f'Current dp[{i}][{k}]: {dp[i][k]}')
min_cost = min(dp[N][1:K + 1])
duration=time.time()-start
print(min_cost)
print(f"Duration:{duration:.4f}s")
# 基于分治DP算法将时间复杂度从N^2降到NlogN
def code2_fast():
import sys
input=sys.stdin.readline
N,K=map(int,input().split())
a=list(map(int,input().split()))
import time
start=time.time()
prefix=[0 for i in range(N+1)]
for i in range(N):
prefix[i+1]=prefix[i]+a[i]
def cal_cost(l,r):
if l>=r:
return 0
mid=(l+r)//2
left_cost=a[mid]*(mid-l)-(prefix[mid]-prefix[l])
right_cost=(prefix[r+1]-prefix[mid+1])-a[mid]*(r-mid)
return left_cost+right_cost
INF=10**18
# 使用dp_previous(k-1 stages)和dp_current(k stages)
def dp_with_k_intervals(l,r,optiml,optimr):
# 边界条件不能取等号
if l>r:
return
mid=(l+r)//2
upper=min(mid-1,optimr)
best=INF
best_j=-1
for j in range(optiml,upper+1):
if dp_previous[j]==INF:
continue
val=dp_previous[j]+cal_cost(j,mid-1)
if val<best:
best=val
best_j=j
dp_current[mid]=best
dp_with_k_intervals(l,mid-1,optiml,best_j)
dp_with_k_intervals(mid+1,r,best_j,optimr)
dp_previous=[INF]*(N+1)
dp_current=[INF]*(N+1)
dp_previous[0]=0
dp_current[0]=0
total_cost=INF
for k in range(1,K+1):
dp_with_k_intervals(k,N,k-1,N)
dp_previous=dp_current[:]
if dp_current[-1]<total_cost:
total_cost=dp_current[-1]
duration=time.time()-start
print(total_cost)
print(f"Duration:{duration:.4f}s")
注意:建议大家考试的时候如果Python写的代码用Python3运行超时的话更换PyPy3,会快很多,在我"山穷水复"的时候,问AI并且更换了PyPy3,原本要2秒多和250多兆字节的程序,用PyPy3只需要不到250毫秒和75兆字节。
当然,如果没有PyPy3可以选择,就说明你的算法时间复杂度不是最优的,就要使用更优化的算法,但是一般而言也能通过部分测试用例------比如这道题使用普通的双循环遍历二维DP算法,时间复杂福N^2,通过率也有60%,如果是300分的题目拿下180分也很值了。
后面优化使用时间复杂度N*logN的二分递归二维DP算法,通过率终于来到100%。


笔者特地下载了用时最长的最后一个单元测试,在这个测试中N=5000,K=50。如果使用N^2复杂度的代码,用时接近400秒。但是使用分治DP,用时1.94秒,
=587.0,但是还有一些基本的外层循环和基本数组构建的代码是公用的,所以最后只快了200倍左右。然而使用塔子哥官网的PyPy3运行同样的程序,只需要250毫秒,速度又提升了8倍左右,相信读到这里大家也知晓为什么产业界和学术界一直在说"优化优化"了吧。排序有优化,像著名的bubblesort就出过很多版本的优化,还有基于二分法的排序算法mergesort等等基于决策边界的单调性原理,动态规划也可以使用二分法进行优化:
- 我们用
表示使得
达到最优的那个
值。 - 决策单调性告诉我们:随着
的增大(处理的前缀越来越长),最优的切割点
绝不会往回走。 - 即:如果
,那么一定有
。
除了在资源有限场景下的模型量化可以用到二维(分治)的动态规划算法,还有一场景这道题的思想也可以应用,不过数组的排序方式不一定是按照数值大小升序或者降序(这道题基于降序的答案没有区别,只需要在cal_cost(l,r)函数加入一个abs()绝对值函数)排列,也可以按照时间或者自定义的排序方式:
- 📊 数据科学:特征分箱(离散化)
这是机器学习特征工程中最常见的预处理步骤。
- 场景:面对连续型特征(如用户年龄、收入、点击率预估中的历史CTR),很多线性模型(如LR)对离散特征更友好。
- 你的算法如何用:你需要把连续值分成K个桶(Binning)。最常用的方法是等频分桶,但等频不一定误差最小。你的算法可以保证:在给定必须把数据切成K段的情况下,每段用中位数(经验上比均值更稳健,不易受离群点拉偏)作为代表值,使得总的信息损失(绝对误差)达到全局最小。 这能显著提升后续模型的泛化能力。
- 📈 时序数据压缩与存储(节省数亿成本)
对于大厂的海量监控、日志和埋点数据(如Prometheus指标),每天动辄PB级。
- 场景:为了节省存储空间,需要将一段平稳变化的时序数据压缩成"阶梯状"的恒定值。
- 你的算法如何用:给定一个时间序列(按时间排序),你可以用你的算法找到最合适的K个切分点,把时间轴分成K段,每段只存一个平均值/中位数。在保证压缩率和恢复精度(误差最小)之间,你的算法提供了数学上的最优解。这在大数据存储引擎(如InfluxDB、ClickHouse的压缩算法)中有极高的工程价值。
- 🏭 智能运维(异常检测与分段)
- 场景:服务器CPU、网络延迟在一天内有明显的波峰波谷。运维需要知道哪些时段属于"高峰期",哪些属于"低峰期",从而制定弹性伸缩策略。
- 你的算法如何用:将历史数据排序(或按时间排序),用你的算法切割成K段。如果某个时刻的数据严重偏离其所在段的"中位数基准线",你就能精准判定为异常点。同时,切分出来的段边界,天然就是"动态阈值"的调整边界。


的位置偏置并加到注意力分数上。
时进行旋转,之后注意力计算零额外开销。