名企AI面试100题知识地图:五章复习与易错点清单

发布时间:2026/10/31 21:28:21
名企AI面试100题知识地图:五章复习与易错点清单

简介:《名企AI面试100题1》是一份面向求职者与计算机专业学习者的AI及开发岗面试题整理,聚焦计算机语言基础,覆盖C++与C混合调用、多线程与多任务、Java类初始化顺序、死锁编写、ArrayList遍历删除、Linux CPU与进程查看、top内存指标、iptables拒绝规则、网卡硬盘诊断及Python列表去重等高频考点。题目配有简明解析和示例代码,便于理解原理、对照练习与面试前快速回顾,也能帮助读者定位基础薄弱环节。资源包共1个PDF文件,约49.22MB,适合在电脑或移动设备上阅读检索。已有251人学习下载,可作为名企技术面试基础环节的针对性训练材料,并为后续算法、大数据、机器学习等方向复习打底。

1. 知识地图:五章一百题到底覆盖了什么

把这份《名企AI面试100题》摊开,第一眼不要扎进单题,而是先看它的五章骨架:语言基础、算法与大数据、机器学习、深度学习、应用方向。它像一张被压缩过的地图,100 道题只是坐标点,真正的复习价值在于你知道每个点挂在哪个模块上。语言基础考链接、并发、集合与 Linux 命令;算法与大数据考链表树数组,再叠加海量数据套路;机器学习与深度学习各有一条从原理到调参的主线;应用方向把 CV、NLP、推荐、风控串成场景题。适合已经学过一轮、需要查漏补缺的人,也适合面试前快速定位薄弱模块的人。先看地图,再拆模块,最后用易错点收口。

2. 语言基础:从 extern "C" 到 Python 列表的必考点

语言基础这一章看起来杂,实际上可以归成四类:链接与符号、并发与初始化顺序、集合与系统排障、Python 基础语法。复习时不要按题号死背,而要问自己:这道题考的是编译链接阶段、运行时阶段,还是操作系统层面的观察手段。把阶段分清,很多答案就能自己推出来。

2.1 C/C++ 链接与名称修饰:extern "C" 的真正动机

C++ 支持函数重载,编译器会把函数名、参数个数和参数类型一起编进符号名,这个过程叫名称修饰。C 语言不支持函数重载,符号名通常只保留函数名本身。于是同一个函数foo(int, int),C 编译器生成的符号接近_foo,C++ 编译器生成的符号可能接近_foo_int_int。链接器只认符号名,名字对不上,链接就会失败。extern "C"的作用不是“让函数变成 C 语言”,而是告诉 C++ 编译器:这段声明按 C 的规则生成和查找符号,不要做名称修饰。

// moduleA.h:C++ 侧声明一个按 C 规则链接的函数 #ifndef MODULE_A_H #define MODULE_A_H extern "C" int add(int x, int y); #endif
// moduleB.cpp:调用方包含头文件后正常调用 #include "moduleA.h" int main() { int result = add(2, 3); // 链接器查找的是未修饰的 add 符号 return result; }

上面两个代码块的关键点在头文件:extern "C"写在声明处,调用方包含头文件时就能继承这个链接约定。如果 C++ 要引用 C 头文件,常见写法是用extern "C" { #include "cExample.h" }包住;反过来,C 代码引用 C++ 中导出的函数时,C++ 头文件里要写好extern "C",C 文件里只按普通extern声明,不能直接包含带extern "C"的 C++ 头文件,否则 C 编译器不认识这个语法。复习时最容易漏掉的是“声明与定义的一致性”:一边加了extern "C",另一边没加,链接器就会去找两个不同的符号。

2.2 Java 初始化顺序与死锁:两个高频“顺序题”

Java 类初始化顺序是典型的“背结论不如写一遍”的题。结论可以压缩成:父类静态块和静态字段先于子类静态块和静态字段;静态部分只在类第一次加载时执行;然后父类普通代码块和普通字段、父类构造方法;最后子类普通代码块和普通字段、子类构造方法。静态块与静态字段是并列优先级,按代码出现顺序执行;普通块与普通字段也一样。

class Parent { static { System.out.println("Parent static block"); } { System.out.println("Parent normal block"); } Parent() { System.out.println("Parent constructor"); } } class Child extends Parent { static { System.out.println("Child static block"); } { System.out.println("Child normal block"); } Child() { System.out.println("Child constructor"); } } public class InitOrderDemo { public static void main(String[] args) { new Child(); // 观察输出顺序 } }

这段代码的输出会先走父类静态、子类静态,再走父类普通块、父类构造、子类普通块、子类构造。参数说明只有一点:静态部分只执行一次,第二次new Child()不会再打印静态块。死锁题则要抓住四个必要条件:互斥、占有且等待、不可剥夺、循环等待。手写死锁时,两个线程各自先锁住一把锁,再请求对方那把锁,顺序相反就会互相等待。

// 死锁示意:两个线程以相反顺序获取同一对锁 Object lockA = new Object(); Object lockB = new Object(); Thread t1 = new Thread(() -> { synchronized (lockA) { try { Thread.sleep(50); } catch (InterruptedException ignored) {} synchronized (lockB) { System.out.println("t1"); } } }); Thread t2 = new Thread(() -> { synchronized (lockB) { try { Thread.sleep(50); } catch (InterruptedException ignored) {} synchronized (lockA) { System.out.println("t2"); } } });

这段代码的重点不是运行结果,而是“相反顺序”四个字。破坏循环等待最常见的做法是给锁定义全局顺序,所有线程按同一顺序获取;也可以使用带超时的尝试锁,避免无限等待。面试里只写两个synchronized嵌套还不够,要能说清为什么它会卡住。

2.3 集合遍历删除与 Linux 排障命令

ArrayList在 for 循环里直接删除元素,常见翻车点是ConcurrentModificationException。原因是迭代器内部维护了一个修改计数,集合结构被直接改动后,下一次next()会检查计数不一致。解决方式有三种:用Iterator.remove()、用removeIf()、或者换成并发安全的集合。前两种更适合大多数业务代码。

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c")); // 方式一:迭代器删除 Iterator<String> it = list.iterator(); while (it.hasNext()) { if ("b".equals(it.next())) { it.remove(); } } // 方式二:removeIf,本质仍是迭代器安全删除 list.removeIf("c"::equals);

Linux 部分要能把命令和观察目标对上。lscpu看 CPU 架构、物理核与逻辑核;top里%MEM是内存使用率,RES是驻留内存,SHR是共享内存;ps aux看进程快照;ifconfig或ip addr show看网卡状态;硬盘健康看smartctl的 SMART 信息。iptables 题则要分清链、源地址、协议、端口和动作。

# 拒绝来源 IP 192.168.1.101 访问本机 80 端口 iptables -A INPUT -s 192.168.1.101 -p tcp --dport 80 -j DROP

参数含义:-A INPUT追加到入站链,-s指定源地址,-p tcp指定协议,--dport 80指定目标端口,-j DROP表示直接丢弃。若写成REJECT,对端会收到拒绝响应;DROP则是静默丢弃。复习时不要只背命令,要能解释“加在哪条链、匹配什么、动作是什么”。

2.4 Python 基础:去重、lambda、深浅拷贝

Python 去重最顺手的写法是list(set(...)),但它有两个坑:结果无序,元素必须可哈希。如果元素是列表或字典,就不能直接塞进 set。需要保持顺序时,可以用字典的键去重,或者手动遍历加集合辅助。

# 保序去重:适合元素可哈希的场景 def unique_keep_order(items): seen = set() result = [] for item in items: if item not in seen: seen.add(item) result.append(item) return result

lambda是匿名函数,适合作为短小的回调或排序键,不适合塞复杂逻辑。深浅拷贝的区别要落到可变对象上:赋值只是多一个引用;浅拷贝创建新容器,但内部可变元素仍共享;深拷贝递归复制内部对象。目录文件名题则可以用os.listdir或pathlib.Path.iterdir,前者返回名称列表,后者返回路径对象,过滤文件时更直观。语言基础这一章复习到最后,应该能做到:看到题目先判断它考编译链接、运行时对象生命周期、集合结构修改,还是系统观察命令。

3. 算法与大数据:链表、树、数组与海量数据套路

算法与大数据这一章的主线不是“刷多少题”,而是把题型归到数据结构上:链表题看指针操作,树题看遍历与递归定义,数组题看双指针、二分和动态规划,海量数据题看分治、哈希和堆。每道题背后都有一个可复用的套路,复习时把套路抽出来,比记住某道题答案更稳。

3.1 链表与树:判环、B 树、有序链表转 BST

单链表判环的标准解法是快慢指针。慢指针走一步,快指针走两步,如果存在环,两者一定在环内相遇;如果快指针走到空,说明无环。这个题的重点不是“会不会写”,而是能不能解释为什么快慢指针一定会相遇:在环内,快指针相对慢指针每次靠近一步,距离最终会缩到零。

class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def has_cycle(head: ListNode) -> bool: slow = fast = head while fast and fast.next: slow = slow.next # 慢指针走一步 fast = fast.next.next # 快指针走两步 if slow is fast: return True return False

B 树的插入与删除是另一类高频题。复习时抓住“阶”的定义:每个节点最多有多少个孩子、最少有多少个孩子,关键字数量与孩子数量差一。插入先落到叶子,再向上分裂;删除先借兄弟,借不到再合并。很多答案写得长,其实核心就是“保持所有叶子在同一层”和“节点关键字数量在上下界内”。有序链表转二叉搜索树则考分治:链表不能随机访问,所以要么先转数组再递归取中点,要么用快慢指针找中点,递归构造左右子树。要能说清为什么必须选中间节点:为了平衡。

3.2 数组与动态规划:子序列、连续子数组、金字塔路径

最大连续子数组和是动态规划的入门题。定义dp[i]为以i结尾的最大和,转移只有两种选择:接上前一段,或从当前元素重新开始。状态压缩后只需要一个变量。

def max_subarray_sum(nums): current = best = nums[0] for x in nums[1:]: current = max(x, current + x) # 要么重开,要么接上 best = max(best, current) return best

金字塔最小路径之和则是二维动态规划:从顶部到底部,每个位置只能从左上或正上方来,取较小值累加。严格单调递增数组找a[x] == x可以用二分:如果a[mid] > mid,说明右侧更不可能相等,往左找;如果a[mid] < mid,往右找。交替字符串题要看两个字符串能否交错组成目标串,用二维布尔 DP 或滚动数组,核心是“最后一个字符来自谁”。这一组题复习时要以“状态定义”为中心,不要一上来就写循环。

3.3 海量数据:Top K、Top IP 与并行计算框架对比

海量数据题最容易背成模板,实际要按数据规模选路线。找重复出现次数最多的前 100 个关键字,常见做法是哈希分片到多个文件,每个文件单独统计,再用小顶堆维护 Top 100,最后合并。找访问某搜索站点次数最多的 IP 也是同一套路:先哈希分桶,保证同一 IP 落到同一桶,再桶内计数,最后堆排序。关键点是“分而治之”之后,每个桶都能放进内存。

对比项Hadoop MapReduceSpark
计算模型磁盘为主的批处理,Map 和 Reduce 两阶段内存计算为主,支持 DAG 执行
中间结果多落磁盘,容错靠重算可缓存到内存,迭代计算更快
适用场景超大规模型批处理、离线统计迭代算法、交互式分析、机器学习流水线
复习重点分片、Shuffle、容错RDD 血缘、宽窄依赖、缓存与 Checkpoint

这张表不要死背,要能解释“为什么迭代算法更偏向 Spark”:因为多轮计算可以复用内存中的中间结果,减少磁盘往返。海量数据题最后都要落到复杂度:分片是否均匀、堆的大小是否可控、合并阶段是否只处理候选集。

4. 机器学习:从 SVM 到 GBDT 的复习主线

机器学习这一章的题量最大,但主线只有三条:模型原理、特征与评估、过拟合与正则化。复习时不要按题号从第一题背到最后一题,而要先把模型按“判别式/生成式”“参数化/非参数”“树模型/非树模型”分堆,再往每堆里填细节。这样遇到陌生题,也能判断它问的是边界、损失函数、优化方法还是评估指标。

4.1 模型原理:SVM、逻辑回归、贝叶斯与 EM

SVM 的核心是“最大间隔”:在能分开数据的超平面里,选离最近样本最远的那个。硬间隔要求完全分开,软间隔引入松弛变量容忍噪声,核函数把低维不可分映射到高维。复习时要能说清支持向量是什么:只有它们决定最终超平面,其他样本删掉不影响结果。逻辑回归为什么要对特征离散化?常见解释是离散化后每个区间有独立权重,能拟合非线性,同时对异常值更鲁棒,还方便特征交叉。贝叶斯定理则是“先验乘似然,归一化得后验”,朴素贝叶斯假设特征条件独立,所以计算快但假设强。EM 算法解决含隐变量的最大似然估计,E 步求隐变量后验,M 步更新参数,本质是下界优化。

对比项判别式模型生成式模型
建模对象直接建模 $P(yx)$
代表逻辑回归、SVM朴素贝叶斯、隐马尔可夫
优点分类边界直接,通常精度高能生成样本,小数据下先验有用
注意点需要足够数据估边界条件独立假设可能过强

4.2 树模型家族:RF、GBDT、XGBoost、Adaboost

随机森林是 Bagging 思路:多棵树并行训练,每棵树用自助采样和随机特征子集,最后投票或平均。GBDT 是 Boosting 思路:串行训练,每棵新树拟合前一轮的残差。XGBoost 在 GBDT 上做二阶泰勒展开,目标函数同时用一阶导和二阶导,并加入树复杂度正则项。为什么用泰勒展开?因为把损失函数近似到二阶后,叶子权重有闭式解,分裂增益可以直接算,工程上还能并行找分裂点。Adaboost 则是通过调整样本权重,让错分样本在下一轮更受关注,最后按弱分类器权重加权投票。

模型核心思路并行性复习重点
随机森林Bagging + 随机特征树间可并行袋外误差、特征重要性
GBDT拟合负梯度/残差树间串行学习率、树深、欠拟合与过拟合
XGBoost二阶泰勒 + 正则项特征分裂可并行目标函数、增益公式、缺失值方向
Adaboost样本权重更新串行弱分类器权重、指数损失

4.3 特征工程与评估:归一化、离散化、特征选择、AUC

归一化是把特征缩放到同一量纲,常见作用是让梯度下降更稳、让距离度量更公平。标准化是减均值除标准差,适合近似正态的特征;归一化通常缩到固定区间。树模型为什么不需要归一化?因为树在某个特征上只看阈值切分,单调变换不改变分裂顺序,所以量纲影响小。但线性模型、KNN、SVM、神经网络对尺度敏感,复习时要把模型和预处理配对记。

AUC 的物理意义可以理解为:随机抽一个正样本和一个负样本,模型给正样本打分高于负样本的概率。它不依赖具体阈值,所以适合评估排序能力。特征选择常见三类:过滤式看统计量,包裹式看模型性能,嵌入式靠正则化或树模型重要性。缺失值处理要看缺失机制:随机缺失可以均值/中位数/模型补,非随机缺失要把“缺失”本身做成指示特征。KNN 的过程则是:算距离、取前 K 个、投票或平均;K 小容易过拟合,K 大容易欠拟合。

4.4 过拟合、正则化与模型对比

过拟合是训练集表现好、验证集表现差。解决方向有:增加数据、简化模型、早停、正则化、Dropout、数据增强、集成。正则化 L1 倾向于稀疏,L2 倾向于让权重变小;在损失函数里加惩罚项,本质是限制模型复杂度。决策树、回归、SVM、神经网络各有优缺点:树模型可解释但容易过拟合;线性回归简单但拟合能力有限;SVM 在小样本高维数据上有优势但核矩阵开销大;神经网络拟合能力强但调参和數據需求高。最大熵模型则是在满足约束的前提下选熵最大的分布,和逻辑回归有很深的联系。贝叶斯网络用有向无环图表示变量条件依赖,适合做概率推理。复习这一章,最后要能在一张白纸上画出“模型—损失—优化—评估”的链条。

5. 深度学习与应用:五个最容易翻车的易错点

深度学习与应用这一章横跨神经网络基础、CNN、RNN、注意力、NLP、推荐和风控。它的特点是名词多、链路长,复习时最容易出现“每个词都见过,连起来说不清”的状态。下面先按模块把主线串起来,再把最容易翻车的五个细节单独拎出来。每一个易错点都按“易漏点—为什么漏—怎么补”拆开,方便直接对照错题本。

5.1 神经网络基础:ReLU、梯度消失与 BN

ReLU 比 sigmoid、tanh 更常用,原因有三:正区间梯度不饱和,计算简单,稀疏激活。sigmoid 在两端梯度接近零,深层网络容易梯度消失;tanh 虽然零中心,但两端同样饱和。梯度消失和梯度爆炸的缓解手段包括:换 ReLU 类激活、合理初始化、批归一化、残差连接、梯度截断、调小学习率。判断梯度爆炸不能只看 loss 曲线,还要看梯度范数、参数范数是否突然变大,以及是否出现 NaN。

BN 的重点是训练和推理行为不同:训练时用当前 batch 的均值和方差,并维护滑动平均;推理时用滑动平均后的统计量。很多人只记住“BN 能加速收敛”,却说不清 batch 大小对它的影响。batch 太小时,统计量噪声大,BN 效果会抖;这时可以考虑 LayerNorm 或 GroupNorm。反向传播复习要抓住链式法则:每层局部梯度乘以上游梯度,缓存前向激活可以避免重复计算。

5.2 CNN 与目标检测:卷积、anchor、NMS、IoU

CNN 的核心是局部连接、权值共享和池化降维。卷积核在空间上滑动,提取局部模式;感受野是输出特征图上一个点对应原图的区域大小,堆叠卷积和池化会扩大感受野。目标检测里,anchor 是预设的参考框,模型预测相对 anchor 的偏移和置信度;IoU 是交并比,衡量两个框的重叠程度;NMS 是非极大值抑制,按得分排序后删掉与高分框 IoU 过大的框。

对比项one-stage 检测two-stage 检测
流程直接回归框和类别先生成候选区域,再分类回归
速度通常更快通常更慢
精度小目标有时偏弱精度通常更稳
代表思路稠密采样 + 直接预测候选框 + 第二阶段修正

边缘检测看梯度变化,Harris 角点看窗口移动后灰度变化大的位置,角点适合做特征点是因为它在多个方向都有明显变化,匹配时更稳定。图像检索题则要从“召回+重排”想:先做粗粒度特征索引,再做细粒度比对,海量图像下要考虑向量量化和倒排。

5.3 RNN/LSTM、注意力与 Transformer

RNN 按时间步展开,隐藏状态传递历史信息,但长序列容易梯度消失。LSTM 用遗忘门、输入门、输出门控制细胞状态,缓解长依赖问题。注意力机制则是让模型在解码时动态关注输入的不同位置,Transformer 把注意力做成自注意力,每个位置都能和序列中其他位置交互,再叠加位置编码、残差和 LayerNorm。复习时要能说清“自注意力为什么能并行”:因为它是矩阵运算,不依赖时间步递归。也要能说清复杂度:序列长度的平方,长序列下要考虑稀疏化或分块。

5.4 应用方向:NLP、推荐与风控的常考链路

NLP 方向常从 TF-IDF 和 word2vec 起步。TF-IDF 用词频乘逆文档频率,衡量词对文档的代表性;word2vec 用上下文预测或中心词预测得到词向量。预训练技术从静态词向量走到上下文表示,再到大规模预训练加微调。推荐方向要能串起召回、排序、重排:协同过滤看用户-物品共现;冷启动分用户冷启动和物品冷启动,常用侧信息、热门兜底、探索策略;LFM 隐语义模型把用户和物品映射到隐空间;wide&deep 用宽侧记记忆、深侧记泛化;FM 用隐向量交叉代替二阶特征交叉。风控方向常问 WOE 编码,原因是它把非线性关系变成线性,同时处理缺失和异常值;样本量题没有标准答案,要结合特征维度、正负样本比例和模型复杂度说明。

5.5 易错点:五个最容易翻车的细节

易漏点一:归一化和标准化混着用。为什么漏:两者都叫“缩放”,很多笔记只写公式不写适用场景。怎么补:记住标准化是减均值除标准差,归一化是缩到区间;线性模型、KNN、神经网络优先标准化,树模型可以不做,但要做缺失值处理。

易漏点二:BN 训练和推理行为分不清。为什么漏:只看过“BN 加速收敛”的结论,没注意滑动平均。怎么补:自己写一遍训练前向和推理前向,标出均值方差来源;再想 batch 很小时为什么效果会抖。

易漏点三:NMS 只背流程,不说阈值影响。为什么漏:把 NMS 当成固定后处理,忽略 IoU 阈值和得分阈值。怎么补:用两个重叠框手算一次 IoU,再分别设高阈值和低阈值,观察保留框数量变化;高阈值保留多,低阈值删得狠。

易漏点四:冷启动只答“用热门补”。为什么漏:只记了兜底策略,没分用户侧和物品侧。怎么补:按“新用户—新物品—新系统”三类分别写策略:新用户用注册信息或热门,新物品用内容特征或探索流量,新系统先做规则再逐步上模型。

易漏点五:梯度消失和梯度爆炸只看 loss。为什么漏:loss 不降就归因于梯度问题,忽略学习率、数据、初始化。怎么补:同时看梯度范数、参数范数、激活值分布;梯度爆炸优先梯度截断和调小学习率,梯度消失优先换激活、加残差、检查初始化。

6. 复习清单:从 100 题回到知识地图

最后两周不要再从头刷题,而是用“地图—错题—自测”三步收口。先拿一张纸默写五章骨架,每章下面只写三个关键词:语言基础写“链接、初始化、排障”,算法写“指针、DP、分治”,机器学习写“模型、特征、评估”,深度学习写“激活、卷积、注意力”,应用写“召回、排序、场景”。写不出来的那一章,就是接下来要补的模块。

复习顺序自测问题补漏动作
语言基础extern "C" 解决的是编译期还是链接期问题手写一个 C++ 调 C 的最小例子
算法与大数据快慢指针为什么一定会相遇手写判环和最大子数组和
机器学习XGBoost 为什么要二阶展开推一遍分裂增益的直觉
深度学习BN 训练和推理差在哪画一张训练/推理流程图
应用方向冷启动分几类,各用什么策略每类写两条可落地策略

错题本不要抄答案,只记三行:这题考什么、我错在哪个判断、下次先看哪个关键词。比如“ArrayList 删除”错在把“遍历”和“修改”混在一起,下次先看是否用了迭代器;“NMS”错在忘了阈值,下次先写 IoU 公式再写流程。每道错题隔三天回看一次,能用自己的话讲通才算过。

我自己的血泪经验是:第一次复习时总想按题号从头刷,结果刷到第 60 题,前面 30 题的模型对比已经混了。后来每次开始新一章,我都强制先画一张本章地图,再把错题挂到地图的节点上;地图上挂不满的节点,就是没复习透的地方。从那以后我每次刷题都强制走一遍“先地图、再错题、后自测”,比单纯堆题量稳得多。希望帮到你。

本文还有配套的精品资源,点击获取