
2023年春招季奇安信算法岗的这份试卷1我在考后做了完整复盘也和不少一起参加笔试的同学对了下答案。今天把整份试卷涉及的算法方向核心考点系统整理出来包括数据结构与经典算法、机器学习、深度学习、以及奇安信这类安全公司特有的安全算法题。如果你正在准备安全厂商或大型互联网公司的算法岗笔试这份复盘能帮你快速定位复习方向避开我踩过的坑。先说结论这份试卷的难度不算“变态难”但覆盖面非常广。选择题部分对基础概念的熟练度要求很高尤其喜欢在KMP、排序稳定性、损失函数这些细节上做文章编程题则是典型的“看起来简单、写起来容易漏边界”的风格。整场笔试做下来的感觉是它不是考你会不会某个算法而是考你在有限时间内能不能又快又准地调用你脑子里的算法库。1. 项目概述这份算法试卷到底考了什么1.1 奇安信算法春招笔试的整体印象奇安信的笔试是典型的在线OJ模式题型主要分三块单选题、多选题和编程题。整体时间通常在90到120分钟之间题量不算小。我印象最深的是选择题中关于KMP模式串next数组计算的那道题题目给出的模式串是pabacaba要求手算next数组。这个考点本身不冷门但很多人对next数组的定义和下标起始位置有混淆导致算出来的结果和标准答案差了一个1这种失分是最冤的。另一个直观感受是试卷对“算法选型”的考察非常执着。它不会直接问你“快排的时间复杂度是多少”这种送分题而是给你一个具体场景比如“在近千万级别的日志数据中去重并排序选择哪种算法更合适”然后让你在选项里挑。这时候光记住复杂度表还不够你得理解每种算法在真实数据下的表现比如归并排序的稳定性和额外空间开销、快排在近乎有序数据下的退化风险。编程题部分我做下来感觉它不追求偏题怪题核心还是字符串匹配、动态规划、贪心这几个大方向。但它会在题目描述里加入一些场景化的包装比如“网络流量包匹配”“恶意特征字符串检测”本质上还是考算法本身。我建议在刷题阶段就把这些经典题的代码模板练到肌肉记忆的程度考场上才能省下思考时间。1.2 五大考点板块梳理我把整份试卷的考点归纳成五个板块这五个板块基本覆盖了安全厂商算法岗笔试的高频范围。第一个是数据结构与经典算法包括字符串匹配、排序、二分、堆、贪心、回溯剪枝等这是选择题和编程题的共同基础。第二个是机器学习算法主要集中在聚类、KNN、损失函数、梯度下降、正则化、评估指标这些偏基础的概念题需要你对常用算法的原理和公式有精准记忆。第三个是深度学习相关卷积计算、池化、注意力机制、常见优化器是高频考点整体偏向应用理解而非手推反向传播。第四个是安全特色算法这是奇安信这类安全厂商笔试比较有区分度的地方会涉及国密算法SM2、SM3、SM4的基本特性、规则引擎Rete算法的匹配过程等这些在普通互联网公司的算法题里很少出现。第五个是编程题实战重点考察代码实现能力和边界条件处理。后面我就按这五个板块结合试卷里出现的具体题目和变形逐一拆解题思路、易错点和备考建议。2. 数据结构与经典算法题解析2.1 KMP算法与 next 数组计算题KMP是字符串匹配里最常考也最容易出错的算法这份试卷直接给出了模式串pabacaba要求计算next数组。我先强调一个关键点next数组有几种不同的定义方式有的教材从1开始下标有的从0开始有的存的是最长公共前后缀长度有的存的是“失配时跳转的下标”。如果试卷没有明确说明默认情况下应该看选项里给的数据格式反过来推断它的定义。我在这里按最常见的前缀函数prefix function来演示也就是pi[i]表示子串p[0..i]的最长相等真前后缀长度这个定义在力扣和多数在线OJ里是主流。对pabacaba逐位计算一遍下标 i子串最长相等前后缀长度说明0a0前缀后缀不能取整个子串本身1ab0前缀a不等于后缀b2aba1前缀a等于后缀a3abac0前缀a不等于后缀c4abaca1前缀a等于后缀a5abacab2前缀ab等于后缀ab6abacaba3前缀aba等于后缀aba所以我们得到pi [0, 0, 1, 0, 1, 2, 3]。如果你用的是“next[i]表示i位置失配时跳转的位置”这一定义结果会比pi数组整体右移或整体加1具体取决于模板。这就是为什么我建议平时固定用一种定义写代码、记思路考场上遇到不同表述时先拿一个短字符串手测一下确认定义之后再大规模计算。KMP的核心思想一句话就能概括利用模式串自身的前后缀信息在匹配失败时不回退主串指针只移动模式串指针。笔试中除了手算next数组还可能考“匹配过程中比较了几次”“某一轮失配后模式串滑动到哪个位置”这类细节题。我在复盘时把这些变形都过了一遍最实用的备考方式是同一个模式串把各种定义下的数组都算一遍同时配合小规模匹配过程手推一遍这样不管题目怎么变都能应对。2.2 排序算法对比与稳定性陷阱排序算法的考察在试卷里基本没有缺席但这张卷子出得不老实。它喜欢把稳定性和复杂度混在一起考让你判断“哪些排序算法在平均时间复杂度为O(n log n)的情况下仍然稳定”。答案只有归并排序。下面是我整理的高频排序算法关键性质对照表笔试前务必背到条件反射排序算法平均时间复杂度最坏时间复杂度额外空间复杂度稳定性冒泡排序O(n²)O(n²)O(1)稳定插入排序O(n²)O(n²)O(1)稳定选择排序O(n²)O(n²)O(1)不稳定快速排序O(n log n)O(n²)O(log n)不稳定归并排序O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定选择排序为什么不稳定我举个具体例子数组[5, 5, 3]第一轮找到最小值3和第一个5交换两个5的相对顺序就变了。快速排序不稳定是因为分区时以基准值为界相等的元素会被分到不同侧。堆排序不稳定则是因为堆顶元素和末尾元素交换时可能把相同元素的前后关系打乱。这类“为什么”在笔试里比单纯背结论更重要因为安全厂商很看重工程师对底层原理的理解深度。堆排序在这份试卷里出现的频率也不低尤其考建堆过程。给定一个乱序数组建最大堆要求写出建堆后的数组序列这题很容易错在“下沉”的起始位置。记住从最后一个非叶子节点开始向上调整最后一个非叶子节点的下标是n/2 - 1下标从0开始时。笔试时间紧张建议提前在纸上多练几次手写建堆过程否则很容易在调整顺序上绕晕。2.3 贪心、二分、堆的实际应用场景题贪心算法在这份试卷里主要以应用题形式出现比如区间调度、跳跃游戏、股票买卖。股票买卖那道题几乎是必考的给定一个价格数组最多只能持有一股求最大利润。如果用贪心做只要把所有的上涨差值都累加起来就行因为不限制交易次数。这里有个很常见的误区有人会把“最多交易1次”和“不限制交易次数”搞混导致写成两种不同的解法。我建议刷题时把这两道变体放在一起做对比考场上看到题眼就能快速分支。二分查找也考了不止一道但变形度很高。比如“在旋转有序数组中查找目标值”“找到某个时间点之前所有日志中的最后一个有效记录”核心还是在边界条件的处理。二分查找的死循环问题很经典当left mid时mid的取值必须向上取整mid (left right 1) // 2否则在区间只剩两个元素时会陷入死循环。这种细节不值得在考场上现场思考考前就应该形成自己的固定模板。堆在试卷里出现在“求数据流中第K大元素”“Top K问题”这两种经典场景中。用最小堆维护最大的K个数这个思路要熟练到不用过脑子。题目如果问“在海量日志中统计出现频率最高的K个IP”套路就是先用哈希表统计频次再用堆筛选Top K最后把堆里的数据逆序输出。海量数据场景下还要说明内存限制比如不能一次性读入所有数据时就用外部排序加分治这块安全厂商的笔试题特别喜欢包装成日志分析场景。3. 机器学习算法核心知识点3.1 聚类与 KNN 高频考点机器学习在选择题里占了相当大的比例其中聚类和KNN是最基础也最常考的两个方向。关于聚类试卷重点考了K-Means的执行过程初始化K个中心点、把每个样本分配到最近的中心点所属簇、重新计算每个簇的中心点、重复直到中心点不再变化。K-Means最明显的短板是初始中心点敏感容易收敛到局部最优所以实际工程中常用K-Means做初始化。这个细节经常作为多选题的一个选项出现。KNN的考点通常集中在“三要素”K值的选择、距离度量、分类决策规则。K值太小容易过拟合K值太大又会让分类边界过于平滑距离度量常用欧氏距离和曼哈顿距离分类决策规则普遍是多数表决。试卷里还可能会问“KNN是参数化模型还是非参数化模型”答案是“非参数化模型”因为它并没有在训练阶段学习出一组固定的参数而是把所有训练样本存下来预测时现场计算距离。这里我想提醒一句做这类概念题时题目往往会在选项里混入一个“迁移学习”“强化学习”之类的干扰项不要被选项顺序带跑。复习关键是建立一张“算法画像表”每个经典算法的类型、训练过程、超参数、适用场景、优缺点全部列出来反复记忆。我在考前两周整理了一张这样的表选择题正确率提升非常明显。3.2 损失函数、梯度下降与过拟合损失函数和梯度下降是必考内容常见的出题方式有两种一种是给公式判断它是回归损失还是分类损失另一种是给几个样本手算交叉熵。这里强烈建议把二分类交叉熵公式背到脱口而出L -[y·log(p) (1-y)·log(1-p)]其中y是真实标签p是预测概率。考试时它会给你一组预测概率和真实标签让你算平均损失这题只要公式没记错就是纯计算分。梯度下降的考点集中在批量梯度下降、随机梯度下降和小批量梯度下降的对比。选择题很喜欢这么出“当训练集非常大时以下哪个方案内存开销最小且收敛速度较快”答案通常是随机梯度下降或小批量梯度下降。SGD的问题在于梯度噪声大、收敛路径震荡所以后来提出了带动量的SGD、RMSProp、Adam等一系列改进优化器。Adam在笔试中的定位是“综合了动量和自适应学习率”这句话基本可以应对概念题。过拟合相关的题目则围绕“如何防止过拟合”展开选项包括增加训练数据、正则化、Dropout、早停、数据增强、降低模型复杂度等。这里有个容易混淆的点Batch Normalization主要作用是加速收敛和缓解内部协变量偏移虽然它也有一定的正则化效果但常规答案里它不算标准的防过拟合手段。3.3 搜索与优化算法模拟退火、粒子群奇安信这张试卷还考了一道比较有区分度的题目关于全局优化算法的选择。题目给了一个带大量局部最优解的连续函数最小化问题问哪种算法更适合求解。答案是模拟退火或粒子群这类启发式算法。这和深度学习里的梯度下降形成鲜明对比梯度下降是局部搜索算法碰到非凸函数容易卡在局部最优而模拟退火以一定概率接受更差的解从而有机会跳出局部最优。模拟退火的核心思想是对照物理退火过程温度高时粒子运动剧烈系统更容易接受新状态即使新状态的能量更高随着温度降低接受劣质解的概率逐渐减小最终收敛到稳定状态。算法里的关键参数是初始温度、降温系数和终止温度。实际实现时降温系数通常取0.95到0.99之间温度下降太快容易得到次优解下降太慢则计算量过大。粒子群算法的核心要点则是模拟鸟群觅食行为每个粒子有自己的位置和速度速度更新时参考两个最优位置个体历史最优pbest和全局最优gbest。速度更新公式里的两个系数c1和c2分别控制自我认知和社会认知的权重w是惯性权重较大的w利于全局搜索较小的w利于局部精细搜索。这类算法在笔试中不会让你手写完整代码但会考察参数对搜索行为的影响理解每个参数的含义比背公式更重要。4. 深度学习与安全特色算法题4.1 CNN 与 Transformer 常见计算题深度学习部分的题目偏应用和理解计算量最大的就是卷积输出尺寸的推导。试卷给了一个n×n的输入特征图卷积核大小f填充p步长s输出尺寸用公式out floor((n 2p - f) / s) 1计算。这里最容易出错的是填充方向默认情况下是上下左右各填充p行/列所以输入尺寸会变成n 2p这一点务必在复习时反复确认。另一种常见的计算是参数量估算比如“输入是3通道224×224的图像第一层卷积核大小7×7输出64个特征图这层卷积的参数量是多少”。参数量等于输出通道数 × 输入通道数 × 卷积核高 × 卷积核宽即64 × 3 × 7 × 7 9408偏置项在此基础上加64。这类计算题只要记住参数量与输入输出尺寸无关、只与卷积核形状和通道数有关基本不会失分。Transformer相关的考点主要围绕注意力机制展开核心是QQuery、KKey、VValue三个矩阵的作用。缩放点积注意力的公式是Attention(Q,K,V) softmax(QK^T / sqrt(d_k))V除以sqrt(d_k)的目的是防止点积过大导致softmax进入饱和区梯度消失。笔试常见的考法是出一道简单计算给两个词向量要求手算注意力权重矩阵这需要你对矩阵乘法、softmax归一化流程非常熟练。4.2 国密算法与其他安全算法特色考点这一部分是安全厂商笔试比较有辨识度的地方普通互联网公司几乎不会考。奇安信作为网络安全厂商考察国密算法SM2、SM3、SM4可以说是岗位特色。这三个算法的基本定位要分清SM2是非对称加密基于椭圆曲线密码体制SM3是密码杂凑算法输出256位摘要SM4是分组对称加密算法分组长度128位密钥长度128位。SM4算法尤其爱考轮数答案通常设置成32轮迭代完成加密。它每一轮的结构是将128位数据分成4个32位字其中三个字参与轮函数运算生成新字再与另一个字异或。这里不需要手推轮函数细节但需要记住加解密的结构是对称的——解密密钥是加密密钥的逆序这是分组密码Feistel结构的特点。SM3则对标SHA-256消息填充方式、迭代压缩过程中都用到了布尔函数和置换笔试一般只考输出长度和基本设计原则。规则引擎Drools的Rete算法也是一道特色题它主要解决“大量规则和大量事实之间如何高效匹配”的问题。Rete算法的核心思想是构建一个由Alpha网络和Beta网络组成的匹配网络Alpha网络对单个事实做条件过滤Beta网络把多个条件进行连接匹配。它最重要的特性是保存了节点之间的匹配状态当新事实加入时不需要从头对全部规则重新匹配只需要沿着网络传播新事实实现部分结果的复用。试卷中的典型考法是给你几条规则和一批事实判断某条规则是否被激活或者问“新事实加入后哪些节点的状态会变化”。5. 编程题实战复盘5.1 编程题一KMP 前缀函数实现编程题第一题就是字符串匹配要求实现一个函数计算模式串的前缀函数next数组并用它完成在主串中的匹配。这道题的完整代码模板我整理如下def prefix_function(s): n len(s) pi [0] * n for i in range(1, n): j pi[i - 1] while j 0 and s[i] ! s[j]: j pi[j - 1] if s[i] s[j]: j 1 pi[i] j return pi def kmp_search(text, pattern): if not pattern: return 0 pi prefix_function(pattern) j 0 for i in range(len(text)): while j 0 and text[i] ! pattern[j]: j pi[j - 1] if text[i] pattern[j]: j 1 if j len(pattern): return i - j 1 return -1这里要重点讲一下while j 0 and s[i] ! s[j]: j pi[j - 1]这段回溯逻辑。当匹配失败时不能直接从头开始比较而要利用已经计算出的前缀信息把j回退到pi[j-1]的位置。很多人在手写时容易把下标写成pi[j]导致数组越界或死循环。我在笔试时也差点在这里翻车后来养成一个习惯每次做KMP相关代码先拿一个短字符串在草稿纸上走一遍循环确认下标没问题再提交。题目给的具体测试用例我不太记得原样但和热词里出现的pabacaba高度相关。如果主串是ababacabacaba先用prefix_function算出pi [0, 0, 1, 0, 1, 2, 3]再执行匹配过程第一次匹配成功的起始位置应该是4。这里手推一遍能加深理解强烈建议考前自己走一遍完整过程。5.2 编程题二最长公共子序列第二题是经典的动态规划——最长公共子序列LCS题目表面是“在两个字符串里求最长公共子序列”本质考察二维DP表的构建。代码模板如下def lcs(s1, s2): m, n len(s1), len(s2) dp [[0] * (n 1) for _ in range(m 1)] for i in range(1, m 1): for j in range(1, n 1): if s1[i - 1] s2[j - 1]: dp[i][j] dp[i - 1][j - 1] 1 else: dp[i][j] max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n]状态转移的核心是当前字符相等时累加左上角的值不相等时取上方和左方的较大值。这里有个很容易忽略的细节是dp数组的维度是(m1)×(n1)多出来的一行一列当作空串的边界处理这样初始化时整张表都是0后续递推不用单独写边界条件。如果求的是最长公共子串而不是子序列状态转移逻辑就要改成相等时累加、不相等时直接清零这个区别在笔试里经常作为“送命题”出现。笔试环境里这道题还有一点很坑——输入输出格式。在线OJ通常是多行输入第一行是字符串个数或者直接就是两个字符串有的平台支持一次性读入两行有的平台需要自己split。我在练习中养成的习惯是先用sys.stdin.read().split()一次性读入全部输入再按数量取前两个字符串这样无论平台怎么组织输入都不会出错。5.3 代码的边界条件与复杂度分析编程题除了考算法本身还会在测试用例里埋边界条件。字符串为空、模式串比主串还长、所有字符全部相同、两个字符串完全不一样这四种情况我在做题时都会在脑子里过一遍。以KMP为例如果模式串为空按题目要求应该返回0我的代码里第一行就处理了这个情况如果主串为空而模式串不为空循环体不会执行返回-1这个逻辑也是正确的。复杂度分析也是笔试的一部分。KMP的预处理是O(m)匹配过程是O(n)总体O(mn)很多人只知道它能优化到线性时间却答不出为什么——原因是主串指针永远不会回退每个字符最多被比较一次模式串指针回溯的总次数不超过m次。LCS的时间复杂度是O(mn)空间复杂度O(mn)追问“如何优化空间复杂度”时可以回答滚动数组把二维数组压缩到两行或一行但只能得到长度值无法回溯具体序列。在线OJ的判题对代码格式要求很严格我建议提交前做三件事检查函数签名是否和题目要求一致、确认没有多余的print调试输出、用示例输入跑一遍用例。我见过有同学算法写对了但因为提交的是包含调试输出的版本而没通过这是最可惜的失分方式。6. 备考常见误区与实用经验6.1 考场时间分配建议奇安信这套试卷题量不小我建议按比例分配时间选择题和简答题控制在总时间的40%以内剩下的时间留给编程题。选择题里如果某道题卡住超过3分钟先标记跳过做完后面再回来看。编程题优先做自己最有把握的那道保证至少AC一道题再回头攻坚另一道。我做编程题的习惯是先花一两分钟在草稿纸上理清思路和复杂度再动手写代码。很多时候一上来就写反而容易陷入细节导致代码结构混乱。对于动态规划类题目先画DP表、明确状态转移方程写代码只是把思路翻译成语法而已。草稿纸理思路这个习惯在笔试现场帮了我大忙尤其试卷题干喜欢做场景包装没有提前梳理很容易被带偏。6.2 高频失分点清单结合我自己的失分和周围同学的反馈我把这份试卷的高频失分点整理成一份速查表失分点具体表现解决方案next数组定义混淆不同教程对next数组定义不同算出的答案和标准选项不一致考前固定一种定义考场上先看选项反推排序稳定性记忆错误把选择排序误记为稳定排序用反例记忆如[5,5,3]选择排序翻转顺序损失函数公式写错二分类交叉熵少写一项或漏掉负号背公式时同时记忆一个具体数字例子二分边界死循环left left 1和left mid两种写法混淆形成固定模板判断区间收缩方向卷积输出尺寸计算错误忘记加2倍填充或整数除法方向搞错把公式写在草稿纸上再代入数字在线OJ输入输出格式错误多读一行或少读一行导致全题零分用sys.stdin.read().split()统一处理输入我在备考阶段把这些容易踩的坑整理成了错题本每周翻一遍。考试当天状态紧张时这些错题本能快速唤起记忆比重新翻书效率高得多。6.3 给准备算法岗笔试的同学几点实在建议最后分享几点我在复盘过程中的体会希望能帮你少走弯路。第一不要只刷力扣高频题基础概念的精确记忆同样重要。奇安信这张卷子的选择题覆盖了KMP、排序稳定性、损失函数、聚类、国密算法等多个方向任何一个方向有知识盲区都会直接丢分。建议按照数据结构、机器学习、深度学习、安全算法四个维度建立知识框架每天抽半小时过一遍基础概念。第二代码模板要形成肌肉记忆。KMP的前缀函数、二分查找、快速排序、归并排序、LCS、背包问题、Top K这些经典模板不仅要看懂还要能在5分钟内无错地写出来。考场上没有时间让你慢慢推导所有能提前固化的东西都要提前固化。第三安全特色算法一定要重视。这是奇安信这类安全厂商区别于普通互联网公司的核心考点SM2、SM3、SM4的基本原理Rete算法的匹配流程这些拿分点对算法工程师来说并不难只要提前看过就能轻松拿下不看就只能靠蒙。