
简介《名企AI面试100题1》面向准备名企AI岗位笔试与面试的计算机专业学生及转行求职者聚焦高频基础考点与答题思路的集中梳理。内容节选整理自大型题库覆盖计算机语言基础、算法和大数据、机器学习、深度学习及应用方向等章节并围绕C调用C函数时为何使用extern C、Java类初始化顺序、死锁构造、ArrayList遍历删除、Linux CPU与进程排查、iptables规则及Python列表去重等典型问题给出解析与代码示例便于按章节系统复习和查漏补缺。资源包为1个PDF文件约49.22MB适合在电脑或平板上阅读标注。已有251人学习可用于面试前快速过题、理解常见陷阱并积累规范表达提升现场作答的条理与准确度。1. 这场AI面试考什么五章目录就是一张分值地图很多考生拿到这份「名企AI面试100题」之后第一反应是从第 1 题开始按顺序刷。这是最低效的姿势。这份题库的章节顺序——计算机语言基础、算法和大数据、机器学习、深度学习、应用方向——本身就是一张面试考点地图越靠前的章节越像用来筛人的基础题越靠后的章节越像决定薪资档位的区分题。面试官不会平均用力语言基础两三轮就过机器学习那几十道题才是真正吃掉四十分钟的地方。所以拿分的关键不是刷完 100 道而是先弄清楚哪 30 道决定你是及格还是优秀剩下的题在什么情况下才会被追问到。2. 计算机语言基础extern C、死锁和 Linux 命令的六个必答细节这一章在面试里出现频率最高、单题分值最低。它的作用不是拉开差距而是快速判断你的基础是不是靠背题堆出来的。答题时间通常只有两三分钟所以答法必须短、准、有机制先给结论再说一层原理最后补一句边界或者追问的落点。下面四组题基本覆盖了这一章的高频区。2.1 extern C从符号修饰讲到链接失败这道题的提问方式几乎固定C 程序里调用 C 编译器编译出来的函数为什么要加 extern C 背答案的人会说为了兼容 C这句话只能拿到一半的分因为它没有解释清楚链接期到底发生了什么。真正的机制是符号名。C 支持函数重载同一个名字可以有多个不同参数列表的版本编译器必须把参数信息编进符号名里才能让链接器区分它们这个过程就是名称修饰name mangling。C 语言不支持重载因此编译器不做修饰。于是同一个void foo(int, int)C 编译器产出的符号是fooC 编译器产出的可能是_Z3fooii。链接器只认符号名名字对不上就报undefined reference。extern C的作用只有一个告诉 C 编译器被它修饰的这部分声明按 C 语言的规则生成和查找符号不要做名称修饰。// calc.h —— 一个同时被 C 和 C 源文件包含的头文件 #ifdef __cplusplus extern C { #endif int add(int x, int y); #ifdef __cplusplus } #endif这段代码的关键在__cplusplus宏它只在 C 编译器下被定义所以用 C 编译器编译时extern C这两行会被预处理器整块删掉头文件退化成一条普通声明。很多考生在答题时漏掉这个宏直接用extern C { ... }包住头文件结果这份头文件再也无法被 C 源文件包含一包含就报语法错误。面试官如果追问为什么不直接把 C 源文件也加上 extern C答案就在这儿C 编译器根本不认识这个语法。想在答题时显得有实感可以补一句验证方法# C 侧符号未经修饰 gcc -c calc.c -o calc.o nm calc.o | grep add # 输出形如 T add # C 侧未加 extern C 时符号已被修饰链接必然失败 g -c main.cpp -o main.o nm main.o | grep add # 输出形如 U _Z3addiiT表示该符号在本目标文件里定义U表示未定义、需要链接期从别处找。_Z3addii里的3是函数名长度ii是两个 int 参数这套编码规则在 Linux 上很常见。答题顺序就是现象undefined reference→ 机制名称修饰→ 解法用 extern C 声明配合__cplusplus宏→ 边界只影响声明处可见的代码不影响已有目标文件。2.2 死锁与 ArrayList两道写代码题的评分点写一个死锁这类题白板上写不出来就是直接掉档。它的评分点不在代码多漂亮而在你能不能说清楚我构造的是哪种破坏条件的缺失。死锁有四个必要条件互斥、请求与保持、不可剥夺、循环等待。最省事的构造方式就是让两个线程以相反顺序获取同一对锁制造循环等待。public class DeadLockDemo { private static final Object LOCK_A new Object(); private static final Object LOCK_B new Object(); static void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public static void main(String[] args) { new Thread(() - { // t1先 A 后 B synchronized (LOCK_A) { sleep(100); // 留出时间窗让 t2 先把 B 抢走 synchronized (LOCK_B) { System.out.println(t1 finished); } } }, t1).start(); new Thread(() - { // t2先 B 后 A加锁顺序与 t1 相反 synchronized (LOCK_B) { sleep(100); synchronized (LOCK_A) { System.out.println(t2 finished); } } }, t2).start(); } }sleep(100)不是为了玄学复现而是为了让两个线程各自拿到第一把锁之后再互相请求把时间窗撑开如果没有这个间隔很可能一个线程跑完两个锁程序正常退出看起来像没写对。跑起来之后用jstack pid能看到 Found one Java-level deadlock 以及两个线程互相持有的锁对象这一段如果能主动说出来比代码本身更加分。配套的另一道题是能不能用 for 循环直接删除 ArrayList 里的特定元素。标准错法有两种用下标遍历时删掉一个元素后面的元素整体前移i会跳过紧接着的那个用增强 for 循环删则会抛ConcurrentModificationException。原因在于增强 for 底层是迭代器迭代器在next()里比较modCount和expectedModCount集合被结构性修改而迭代器不知情时就快速失败fail-fast。// 反例下标删除会漏删连续重复元素 for (int i 0; i list.size(); i) { if (b.equals(list.get(i))) list.remove(i); // 删完后 i 自增跳过了下一个元素 } // 正解一用迭代器自己的 removemodCount 会被同步更新 IteratorString it list.iterator(); while (it.hasNext()) { if (b.equals(it.next())) it.remove(); } // 正解二一行搞定内部仍然是迭代器删除 list.removeIf(b::equals);答题时把错在哪、为什么错、怎么改、什么场景改用 CopyOnWriteArrayList四句话说完就够。最后一句是加分项CopyOnWriteArrayList每次写都复制整个数组只适合读多写极少的场景写多的时候性能会崩不要当成万能药。2.3 链表与数组三类模板题的最小可用代码链表判环是这一章最经典的题答法分两层能不能判出有环能不能找到入口。快慢指针同时从头出发慢的走一步、快的走两步有环必然相遇。def has_cycle(head): slow fast head while fast and fast.next: # fast 走两步所以两个判空都要写 slow slow.next fast fast.next.next if slow is fast: return True return False找入口的做法是相遇之后把其中一个指针放回头部两个指针都改成每次走一步再次相遇的位置就是环的入口。why 的解释要能说出来设头到入口距离为 a入口到相遇点为 b环长为 L相遇时快指针比慢指针多走了一圈即 a b nL 2(a b)化简得 a nL - b也就是说从头出发走 a 步、从相遇点出发走 nL - b 步会同时到达入口。def detect_cycle(head): slow fast head while fast and fast.next: slow, fast slow.next, fast.next.next if slow is fast: # 相遇一个指针回头部同速再走 p head while p is not slow: p, slow p.next, slow.next return p # 环的入口 return None数组类题里严格单调递增的整数数组中找 a[x] x 的位置最容易答成线性扫描。观察到数组严格递增则 a[i] - i 单调不减可以二分。def find_fixed_point(a): lo, hi 0, len(a) - 1 while lo hi: mid (lo hi) // 2 if a[mid] mid: return mid if a[mid] mid: lo mid 1 # a[i]-i 单调不减左半区间不可能再有解 else: hi mid - 1 return -1再看最大连续子数组和状态定义只有一句话以当前元素结尾的最大和要么接着前面延续要么从当前元素重新开始。def max_subarray(nums): best cur nums[0] for x in nums[1:]: cur max(x, cur x) # 续上 或 重开二选一 best max(best, cur) return best这三道题放在一起练的价值在于它们代表了链表双指针、有序性二分、线性 DP 三个不同的思考起点。面试官在白板上通常只给一道但会连着追问两个变体比如如果数组不是严格递增而是非递减二分还成立吗——答案是不成立因为 a[i] - i 不再单调得退化成线性扫描或者其他思路。能主动说出这个边界说明你是在推导而不是在背题。2.4 Linux 命令与海量数据命令题答看哪一列数据题答分几步命令类题看着零碎其实有固定答法命令 看哪一列 一句追问。下面这张表把这一章最高频的几条压在一起面试前扫一遍就够。问题命令要看的关键列或参数常见追问几颗物理 CPU、每颗几核lscpuSocket(s)是物理 CPU 数Core(s) per socket是单颗核数逻辑核数 物理核数 × 每核核数 × 超线程倍数内存占用看哪列top%MEM是内存占比RES是驻留内存SHR是共享内存VIRT 虚高不代表真占内存当前有哪些进程ps aux/ps -efSTAT 列看进程状态R 运行、S 睡眠、Z 僵尸僵尸进程怎么清理网卡状态ip addr show/ifconfig收发包计数、错误计数、丢包计数虚拟网卡为什么看不到物理链路硬盘健康smartctl -a /dev/sdXSMART 属性里的重映射扇区、待映射扇区为什么不能只看df -hiptables 那道题的标准写法是把来源 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必须写因为端口只对 TCP/UDP 有意义--dport 80是目的端口-j DROP是静默丢弃。这里有一个高频追问DROP和REJECT有什么区别。DROP不回包客户端只能等到超时REJECT会返回一个拒绝报文客户端立刻失败。线上做封禁一般用DROP做可观测的拒绝用REJECT。海量数据题的代表是从日志里找出访问次数最多的那个 IP或者找出出现次数最多的前 100 个关键字。答题时先给框架再给代码框架是四步分片、统计、归并、取 Top K。单机内存装不下时先按hash(key) % N把数据切成 N 份同一个 key 一定会落到同一份然后每份单独统计最后合并。import heapq, collections def top_k_ips(lines, k100): counter collections.Counter(line.split()[0] for line in lines) # 统计每个 key 的次数 # 小顶堆维护 Top K堆顶是当前第 K 名新元素比堆顶大才替换 return heapq.nlargest(k, counter.items(), keylambda kv: kv[1])用heapq.nlargest的好处是复杂度为 O(n log k) 而不是 O(n log n)k 远小于 n 时优势明显。答题时补一句容量估计更加分10 亿条日志按每行 100 字节算约 100 GB切成 100 份每份 1 GB单机就能跑每份取出的 Top 100 合并后再取一次 Top 100内存里只需要放 100 × 100 个 (key, count) 对。3. 算法与大数据链表判环、Top K 和海量数据题的通用框架这一章的题量在题库里排第二但它真正考的并不是背了多少道题而是面对一个没见过的场景时能不能拆出步骤。面试官在这里最常做的一件事是给一个约束变化——数据量从万级加到十亿级、数组从有序变成无序——然后看你的解法是跟着变还是原地卡住。所以准备策略是把题按考点类型而不是按题目编号归档。3.1 B 树与索引插入删除答到哪一层B 树这类结构题面试官不会真让你手写完整实现他要的是三件事为什么要有它、它的平衡是怎么维持的、它和实际系统里的什么东西对应。B 树的动机是磁盘 IO二叉树在内存里很快但每下降一层就是一次随机 IO几百万节点的树深度几十层代价无法接受。B 树把一个节点撑大到一个磁盘页常见 4 KB 或 16 KB让一次 IO 带回几百上千个键深度压到三四层。插入的答法是所有插入都发生在叶子节点插入后如果节点键数超过上限就分裂把中间键上推到父节点父节点也可能因此再分裂最坏一路传到根根分裂时树高加一。删除更绕如果删完节点键数低于下限通常取 m/2 上取整减一先看兄弟节点是否富余富余就借一个键上来、把父节点的分隔键拿下来兄弟也紧张就合并合并可能导致父节点继续下溢最坏一路传到根根合并时树高减一。这两句话能说顺比默写伪代码有效得多。追问通常落在B 树和 B 树的区别上B 树只有叶子节点存数据、内部节点只存索引键叶子之间用链表串起来所以范围查询可以顺着链表扫而 B 树做范围查询要反复中序回溯。这就是为什么存储引擎几乎都用 B 树。3.2 数组类题从能不能二分开始判断数组题的通用判断链是数组有没有序、有没有单调性、要求的是连续还是子序列、能不能用双指针。有序就优先想二分无序但求连续区间就想滑动窗口或者 Kadane 那一套求子序列就想 DP 或者贪心。数组中的子序列个数这类题容易翻车在计数重复上。如果只求不同子序列的个数DP 定义是以第 i 个元素结尾的不同子序列个数转移时要减去上一次同一个字符贡献的重复部分否则同样的字符出现在不同位置会被重复计数。答题时先把子序列不要求连续这句话说出来再问清是否要求不同因为两者的解法完全不同——这一步主动澄清面试官通常会给正面反馈。金字塔最小路径之和是另一种典型给一个二维三角从顶走到底每次只能走到下一行的相邻位置求路径和最小。自底向上比自顶向下好写因为不用处理边界分支。def minimum_total(triangle): dp triangle[-1][:] # 从最后一行起步 for i in range(len(triangle) - 2, -1, -1): for j in range(len(triangle[i])): dp[j] triangle[i][j] min(dp[j], dp[j 1]) # 只依赖下一行相邻两个 return dp[0]这个写法把空间压成了一维dp[j]在更新时代表从下一行第 j 个位置到底部的最小和所以min(dp[j], dp[j1])就是两条合法路径。面试官如果追问空间能不能再省答案是没法省到 O(1)但可以只保留当前行如果追问路径本身怎么还原就要额外开一个二维数组记录选择。交替字符串考的是双序列 DP判断第三个字符串是否由前两个字符串交错构成。状态是dp[i][j]表示第一个串取前 i 个、第二个串取前 j 个能否拼出第三个串的前 ij 个转移看第三个串的当前字符能不能从第一个串或者第二个串来。这道题的价值在于它同时考了状态定义、边界初始化和滚动数组优化一道题能聊十分钟。3.3 最长连续递增序列别把连续读成递增子序列这道题是坑点密集区。最长连续递增序列要求元素在原数组里相邻一次扫描就够最长递增子序列不要求相邻要 DP 加二分做到 O(n log n)。读题读错整道题的解法全错而且代码跑出来的结果看着也对这是最难受的一类翻车。def find_length_of_lcis(nums): if not nums: return 0 best cur 1 # 单个元素本身就是长度 1 的连续递增序列 for i in range(1, len(nums)): if nums[i] nums[i - 1]: cur 1 # 接着上一段继续 else: cur 1 # 断了从当前元素重开 best max(best, cur) return best注意cur重置成 1 而不是 0因为当前元素自己至少构成长度 1 的序列。这类边界值就是评分点写错一个初始化空数组或者全降序的用例上就露馅。如果面试官改口说不要求连续答题结构要立刻切换定义dp[i]为以第 i 个元素结尾的最长递增子序列长度转移是找前面所有比它小的元素里的最大值加一也就是 O(n²)再优化就是用tails数组维护每个长度对应的最小结尾值因为tails单调可以二分复杂度降到 O(n log n)。能把这两步的演进讲清楚比直接写出最优解更有说服力。3.4 海量数据题的通用四步框架有序链表转换二叉搜索树这类结构题和海量日志找 Top IP这类数据题看起来毫不相干但面试时的答法可以套同一个框架先确定输入输出的规模再确定能不能一次装进内存然后选分治或流式最后给复杂度和失败兜底。有序链表转平衡二叉搜索树的关键是找中点链表不能随机访问所以用快慢指针找中点递归建树。时间复杂度 O(n log n)如果把链表先转成数组可以降到 O(n)代价是 O(n) 额外空间。面试官通常追问能不能不用额外空间答案是可以在递归时同时推进链表指针做到 O(n)但代码可读性会明显下降这个取舍要能说出来。hadoop 和 spark 的对比题属于看起来是八股其实在考你有没有工程判断。答法不要罗列组件名而是抓住三个维度计算模型一个偏批处理的磁盘迭代一个偏内存的 DAG 执行、中间结果一个落盘一个尽量留在内存、适用场景一个适合超大规模稳定批任务一个适合迭代型算法和交互式分析。能补一句迭代次数多的机器学习任务在磁盘模型下会被 IO 拖死这道题就答到位了。4. 机器学习SVM、树模型与特征工程的答题骨架这一章是整份题库的重心题量最大也最容易把时间讲超。面试官在这里的提问逻辑是你知不知道它为什么这么设计而不是你记不记得公式。所以每道题都应该准备一个三层结构一句话定义、一层机制、一个边界。下面按高频聚类拆开。4.1 SVM 与 EM推导题答到什么深度SVM 的完整链条很长几何间隔、间隔最大化、拉格朗日乘子、对偶问题、KKT 条件、核技巧、软间隔。全推一遍要二十分钟实际面试只给五到八分钟所以必须会裁剪。裁剪的原则是保住三个关键节点其余用一句话带过。第一个节点是为什么最大化间隔。直观答案是间隔越大模型对噪声的容忍度越高泛化误差上界越小形式化答案是 SVM 的优化目标就是最小化结构风险间隔出现在正则项的位置。第二个节点是为什么转对偶。两个原因一是原问题的约束是线性的转成对偶后约束变成简单的上下界求解更省事二是对偶形式里样本只以内积出现把内积换成核函数就能处理非线性不用显式映射到高维。第三个节点是支持向量是什么。答案是对偶问题里乘子非零的样本它们恰好落在间隔边界上决定了最终的分类面其余样本删掉不影响结果——这个稀疏性也是 SVM 相对其他模型的优势之一。软间隔要能说清 C 的作用C 越大对误分类的惩罚越重间隔越窄越容易过拟合C 越小容忍更多误分类间隔越宽偏差上升。这个参数往哪边调会怎样的表述比背公式有用得多。EM 算法的答法类似。核心矛盾是有隐变量时对数似然里出现log 求和直接求导解不出来。解法是先用 Jensen 不等式构造一个下界E 步求隐变量的后验期望再最大化这个下界M 步更新参数交替进行保证似然单调不降最终收敛到局部最优而不是全局最优——这句话一定要说因为它是高频追问的答案。# EM 的骨架以混合模型为例 theta init_params() for step in range(max_iter): # E 步固定参数算每个样本属于每个成分的后验概率responsibility resp e_step(data, theta) # M 步固定后验最大化期望对数似然更新参数 theta m_step(data, resp, theta) if converged(log_likelihood(data, theta)): breakE 步和 M 步的先后不能反先有后验才能加权求期望。收敛判据一般用对数似然的变化量小于阈值或者参数变化量小于阈值。如果面试官问EM 一定能收敛到全局最优吗答案是不能它对初值敏感实践中常用的做法是多组随机初值取最优或者用 K-Means 的结果做初始化。4.2 过拟合、正则化与归一化一套逻辑答遍五道题过拟合、欠拟合、正则化、归一化、特征离散化这几道题本质上是同一个知识网络的不同切面。准备的正确方式不是给每道题背一个答案而是准备一条能走通的因果链。起点是偏差方差分解模型误差 偏差² 方差 不可约噪声。欠拟合是偏差大表现是训练集和验证集都差过拟合是方差大表现是训练集很好、验证集明显差。判断依据是学习曲线不是感觉。中间是解决手段的四个层级数据层加样本、数据增强、去噪、模型层降复杂度、加正则、早停、训练层交叉验证、集成、dropout、问题层重新审视特征和标签是否有泄漏。答这道题时按层级说比零散罗列十条有效因为面试官能听出你有体系。终点是正则化。L1 产生稀疏解因为它对接近零的参数惩罚是常数斜率容易把参数压到恰好为零L2 把参数压向零但不为零因为它对大参数的惩罚随数值增长。几何解释是约束区域一个是菱形一个是圆形菱形更容易和目标函数的等高线在坐标轴上相切。这句几何解释是很多人漏掉的加分点。归一化的因果链是另一条不同特征的量纲差距大 → 梯度方向被量纲大的特征主导 → 优化路径呈锯齿状 → 收敛慢甚至震荡。归一化之后各特征尺度一致等高线接近圆形梯度下降走的是近似直线。同时基于距离的模型KNN、K-Means、SVM 的核对尺度敏感不归一化等于给某个特征偷偷加了权重带正则的模型也要求尺度一致否则惩罚力度在不同特征上不公平。树模型为什么不需要归一化这道题的答案只有一个核心树的分裂点只依赖特征内部的相对顺序而单调变换不改变顺序所以归一化对分裂结果没有任何影响。能补一句但如果是带正则的线性模型做 stacking或者用树做特征编码后再进线性层尺度又变得重要说明你知道边界在哪。4.3 树模型家族RF、GBDT、XGBoost 的对比与追问这三者的关系是面试里最常被连着问的一组。答法用一张对比表打底再补两个追问。维度随机森林GBDTXGBoost集成方式Bagging并行训练多棵树Boosting串行拟合残差Boosting串行但内部特征级并行目标降低方差降低偏差降低偏差并加正则控制方差目标函数无显式正则损失函数本身损失函数 树复杂度正则项分裂依据基尼或信息增益负梯度残差二阶泰勒展开后的增益缺失值需要预处理需要预处理分裂时自动学默认方向第一个追问是XGBoost 为什么要用二阶泰勒展开。表层答案是二阶信息比一阶更准收敛更快深层答案是把损失函数抽象掉了——只要损失二阶可导就能代进同一个增益公式于是平方损失、逻辑损失、自定义损失都能用同一套框架同时展开后的目标函数里叶子权重有闭式最优解增益可以直接算出来比较分裂搜索变得很干净。第二个追问是RF 和 GBDT 的区别与联系。区别在并行性和偏差方差RF 的树之间独立靠平均降方差树越深单棵越强但整体靠投票兜底GBDT 的树之间有依赖每棵拟合前面所有的残差靠累加降偏差。联系是两者都是树集成都靠多个弱模型组合成强模型只是组合方式一个是并行平均、一个是串行累加。还有一个高频的细节题为什么 XGBoost 要对特征预排序或者说它的并行到底并的是什么。答案是它并行的是特征维度的分裂点搜索不是树与树之间——树必须串行因为后一棵依赖前一棵的残差。这个区分说清楚能挡掉一大半以为 XGBoost 是并行训练树的错误理解。4.4 特征工程与评估指标离散化、缺失值、AUC特征离散化那道题的答案分四块。第一是稳定性连续值容易受异常值影响分箱之后单个异常点只影响一个箱。第二是非线性离散化相当于给模型加了分段常数的表达能力线性模型也能学到非线性关系。第三是稀疏与效率one-hot 之后稀疏很多实现有稀疏优化计算更快。第四是业务可解释性分箱的边界往往对应业务上的阈值风控和营销场景尤其看重这一点。逻辑回归这类线性模型尤其需要离散化因为它自身学不到特征之间的交互离散化之后再交叉就补上了这块。AUC 的物理意义要一句话说准随机抽一个正样本和一个负样本模型给正样本打分高于负样本的概率。它等价于 ROC 曲线下的面积对排序敏感、对阈值不敏感、对类别不平衡相对不敏感——最后这一点经常被答错很多人以为不平衡会让 AUC 失真实际上失真的是准确率AUC 只关心相对顺序。追问通常问GAUC 是什么、为什么推荐场景更常用答案是按用户分组算 AUC 再加权平均因为全局 AUC 会被活跃用户主导评估的其实是同一个用户内部排序对不对。缺失值处理按模型分树模型可以直接把缺失当单独分支或者填一个明显偏离正常范围的常数线性模型和神经网络一般要填充常用的有均值、中位数、众数、模型预测填充、以及把是否缺失单独作为一个指示特征。最后一点经常被忽略但缺失本身往往带信息比如某个字段缺失意味着用户没有完成某一步操作。特征选择的三类方法要能分清楚过滤式方差、卡方、互信息不看模型、包裹式递归特征消除看模型但计算贵、嵌入式L1 正则、树模型的特征重要性训练过程中完成。特征重要性的局限也要知道基于不纯度的重要性会偏向取值多的连续特征用置换重要性更稳。5. 易错点五类一开口就被追问的失分答法这一章不是新知识是把前面几章里最容易答偏的地方单独拎出来。它们的共同特征是听上去像答对了但一追问就露馅。每条按错在哪、为什么错、怎么答对走一遍。5.1 归一化类题把标准化和归一化混着说错在哪一上来就说归一化就是把数据缩放到 0 到 1然后把 Z-score 标准化也叫归一化接着又给树模型做归一化。为什么错归一化min-max和标准化Z-score是两种不同的线性变换前者依赖最小最大值、对异常值极敏感后者依赖均值和标准差、相对稳一些。在中文语境里归一化常被当统称用但面试时如果不区分后面所有讨论都站不住。至于树模型分裂只看相对顺序单调变换不改变顺序做归一化纯属白费。怎么答对先给一句我理解您说的归一化是指统一量纲具体实现有 min-max 和 Z-score 两种区别在于对异常值的敏感度把口径统一掉再说这套处理对距离类和梯度类模型必要对树模型无效一句话把适用边界划出来。这个开场比直接讲公式稳得多。5.2 过拟合类题只会说加数据错在哪被问过拟合怎么解决答多加点数据就停了或者把欠拟合和过拟合的表现说反。为什么错加数据是有效但最不可控的一招面试官问这道题想听的是你对模型复杂度的理解不是数据够不够。表现说反更致命因为后面所有的解决手段都会用错方向——把过拟合当成欠拟合去加模型复杂度等于火上浇油。怎么答对先给判断标准训练误差小、验证误差大学习曲线上两条线明显张开再按数据、模型、训练、问题四个层级给手段最后补一句具体到这道题我会优先看验证集和训练集的差距有多大差距小说明不是过拟合加正则反而会更差。有取舍的答案永远比清单式的答案得分高。5.3 评估指标类题把 AUC 当成准确率的同义词错在哪说AUC 越高模型越准或者说AUC 对样本不平衡敏感。为什么错AUC 衡量的是排序能力不是分类准确率它和阈值无关因此天然不受类别先验的影响真正受不平衡影响的是准确率、精确率这些依赖阈值的指标。把这两个概念混在一起后面解释为什么用 AUC 而不用准确率就讲不通了。怎么答对一句话给物理意义随机正负样本对正样本得分更高的概率再补一句所以它对阈值不敏感、对排序敏感类别不平衡时比准确率可靠。如果面试官继续问AUC 高但业务效果差是什么情况答线上用的是固定阈值AUC 只保证整体排序具体阈值下的精确率和召回率才决定业务效果这道题就闭环了。5.4 树模型对比题只说XGBoost 用了二阶导错在哪被问 XGBoost 和 GBDT 的区别只答用了二阶泰勒展开然后卡住。为什么错二阶展开只是手段不是目的。它带来的三个实际差异——目标函数里显式加了树复杂度正则、损失函数被抽象成可替换的接口、分裂增益可以直接解析计算——才是面试官想听的。只说二阶导等于只说了实现细节没说清设计动机。怎么答对抓住四点说目标函数加了正则项叶子数和叶子权重平方和控制模型复杂度用二阶展开把损失抽象掉任何二阶可导的损失都能套分裂增益有闭式解搜索更快缺失值在分裂时自动学默认方向。最后补一句它并行的是特征维度的分裂点搜索树与树之间仍然是串行的把最常见的误解提前挡掉。5.5 检测类题NMS 的阈值方向说反错在哪解释非极大值抑制时说两个框 IoU 小于阈值就抑制掉或者说阈值越大保留的框越多所以阈值越大越宽松。为什么错NMS 的逻辑是保留得分最高的框把与它重叠过多的框压掉所以抑制条件是 IoU 大于阈值。阈值越大抑制条件越难满足保留的框反而越多这个方向一说反追问阈值调大对小目标检测有什么影响就必然答错。怎么答对按步骤讲按得分排序、取最高分入保留列表、算它与剩余框的 IoU、IoU 超过阈值的丢弃、重复直到队列空。再补一句参数影响阈值调低会压掉更多邻近框密集场景容易漏检阈值调高保留更多框但重复框会变多。能顺带提一句 soft-NMS 用分数衰减替代直接删除说明你知道这条路的演化方向。6. 答题技巧把 100 题压成「结论—机制—边界」三层刷到一定量之后会发现题目是无限的答法是可以复用的。我自己后来固定用三层结构答所有技术题第一层一句话给结论第二层讲清机制第三层主动划边界。三层各自有明确的时间预算结论十秒机制一分钟边界二十秒。题型第一句话怎么说收尾补什么概念题什么是 BN一句话定义加它解决什么问题训练和推理的行为不一致这点最容易被追问对比题RF 与 GBDT先给最本质的一条差异并行 vs 串行、降方差 vs 降偏差说清什么场景我会选哪个推导题SVM、EM先说目标函数和核心矛盾说清哪一步是近似、哪一步会损失最优性代码题判环、Top K先说思路和复杂度再动手写说清边界用例我怎么测场景题海量数据、冷启动先问清约束数据量、时延、冷热说清这个方案哪里会先崩第三层是最容易被忽略、也最容易拉开差距的地方。面试官判断一个人是背题还是真懂看的往往不是你答得多完整而是你能不能说清这个方法什么时候不适用。比如讲完 XGBoost 的缺失值自动分裂补一句这是训练时学的默认方向如果训练集里某特征完全没缺失推理时出现缺失就只能是默认走一边效果没有保证讲完 AUC补一句它评估的是排序线上阈值还得单独调。这类话不用多一道题一句就够。还有一个习惯值得强制养成写完代码先说边界再等面试官问。链表题先说空链表和单节点数组题先说空数组和全相同元素DP 题先说初始化的含义。我吃过一次亏白板上写快排写完自己觉得挺顺面试官问如果数组里全是相同元素呢我才意识到自己的分区把等于基准的元素全放一边复杂度直接退化到 O(n²)。从那以后我每次写完代码都强制在心里过一遍全相同、已有序、逆序、单元素、空输入这五个用例能过再说下一句。这个动作看起来笨但它救回来的分比多刷二十道题多。题目本身不是目的能把这 100 道题背后的考点分布、答题骨架和边界意识迁移到没见过的题上才是这份题库真正的用法。题库里每道题都配了完整解析章节顺序与在线题库的题号一一对应方便你按模块对着刷、对着改自己的答法。希望帮到你。本文还有配套的精品资源点击获取