尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

2023年58同城算法工程师面试题全解析:六大考点与答题思路

2023年58同城算法工程师面试题全解析:六大考点与答题思路 最近在整理算法面试资料时看到一份流传很广的2023年58同城算法工程师面试题第二版。我把整份题单过了一遍最大的感受是考察面比想象中宽了不少。KMP的next数组、拉普拉斯锐化、音频重采样、PID、Drools的Rete算法、国密SM系列……从底层数据结构到业务算法再到工程落地基本一个没落下。这份题单对准备算法岗位面试的人很有参考价值。它既不是清一色的LeetCode刷题也不是纯理论八股而是围绕“算法工程师在真实业务里要解决什么问题”来出题。如果你正在准备算法岗面试或者想系统性查漏补缺这篇文章可以帮你把涉及的考点全部过一遍顺带把每道题背后的考察意图和答题思路讲清楚。1. 面试题整体拆解这份2023年算法工程师面试题考了什么1.1 从考点分布反推岗位诉求我把题单里涉及的算法方向做了个归类大致能分成六块方向典型考点对应热词数据结构与基础算法KMP、堆排序、快速幂、Dijkstra、贪心、二分图HK、DC3数据结构排序算法、kmp算法、贪心算法机器学习KNN、聚类、XGBoost、强化学习、变分推断机器学习算法、knn算法的应用能力、kl elbo算法图像与信号处理Sobel、拉普拉斯锐化、图像分类、工业异常检测、音频重采样sobel算法、图像锐化的拉普拉斯算法、音频重采样算法控制与状态估计PID、卡尔曼滤波、粒子群、模拟退火pid算法、卡尔曼滤波算法、粒子群算法原理业务与工程化BM25排序、Drools规则引擎、国密算法、SSL弱哈希bm25算法、规则引擎drools的rete算法、sm2 sm3 sm4 zuc深度学习与视觉前沿EVA-02、图像分类算法、异常检测eva-02分类算法、图像分类算法、工业异常检测算法这个分布其实已经能看出来这轮面试不是单纯刷题而是“基础能力业务理解工程素养”的综合考察。尤其是把音频重采样、PID、Rete算法这类偏工程的方向放进来说明面试官很在意候选人是否真的处理过生产环境问题而不仅仅是会写算法题。1.2 为什么58同城的算法岗会考这些58同城的业务场景比较特殊信息分类平台覆盖招聘、房产、二手车、本地生活服务等领域。这类业务的核心算法需求集中在几个地方——搜索排序用户搜“Java开发”怎么把最匹配的职位排前面、推荐召回给用户推哪些二手商品/房源、风控识别判断虚假信息、异常行为以及大量文本图像内容的处理。所以你会发现面试题里出现BM25、KNN、聚类、图像锐化这些内容背后都有业务影子。搜索排序需要相关性和BM25这类检索模型推荐需要聚类和向量召回图片真实性审核需要Sobel边缘检测、图像分类、异常检测这些视觉手段。出题方向其实是跟着业务走的这在面试复盘时尤其值得注意。2. 数据结构与基础算法手撕代码前先理清这三类题2.1 KMP算法的next数组怎么算以p“abacaba”为例题单里有一道很经典的KMP题“对于模式串pabacaba其next数组为多少”。这题看着简单但能完整算对的人比例其实不高因为不同教材对next数组的定义有差异。先说最常用的“前缀函数”定义next[i]表示p[0..i]子串的最长相等真前后缀长度。按这个定义pabacaba的推导过程是next[0] 0单字符没有真前后缀next[1]子串ab前缀a后缀b不相等next[1]0next[2]子串aba最长相等前后缀是a长度为1next[3]子串abac没有相等前后缀next[3]0next[4]子串abaca最长相等前后缀是anext[4]1next[5]子串abacab最长相等前后缀是abnext[5]2next[6]子串abacaba最长相等前后缀是abanext[6]3所以经典前缀函数结果是[0, 0, 1, 0, 1, 2, 3]。有一部分教材把next数组定义为“失配时模式串跳转的位置”也就是next[0]-1后面的值等于前缀函数前一项算出来是[-1, 0, 0, 1, 0, 1, 2]。面试时建议先把定义跟面试官确认清楚再开始算这个小细节反而能加印象分。next数组的手写代码也给一版标准前缀函数写法vectorint getNext(const string p) { int n p.size(); vectorint next(n, 0); for (int i 1; i n; i) { int j next[i - 1]; while (j 0 p[i] ! p[j]) j next[j - 1]; if (p[i] p[j]) j; next[i] j; } return next; }KMP的匹配过程我就不再贴完整代码了关键是记住文本串指针不回退失配时通过next数组确定模式串跳转位置时间复杂度O(mn)。面试时如果直接能写出这段代码再把两种next定义的差异说清基本就稳了。2.2 排序算法堆排序的建堆和下沉容易写错热词里堆排序、冒泡排序C、快速幂算法C都出现了。排序算法是面试手撕代码的重灾区但大家容易忽略的是面试官考排序不是为了看你背不背得出来而是看你对复杂度、稳定性、工程应用的理解。堆排序尤其值得单独练。很多人能说清“大顶堆”“小顶堆”的概念但写代码时容易在heapify这一步忘记递归或者边界判断出错。我贴一版简洁的堆排序核心代码void heapify(vectorint nums, int n, int i) { int largest i; int l 2 * i 1, r 2 * i 2; if (l n nums[l] nums[largest]) largest l; if (r n nums[r] nums[largest]) largest r; if (largest ! i) { swap(nums[i], nums[largest]); heapify(nums, n, largest); } } void heapSort(vectorint nums) { int n nums.size(); // 从最后一个非叶子节点开始建堆 for (int i n / 2 - 1; i 0; i--) heapify(nums, n, i); // 依次将堆顶放到末尾 for (int i n - 1; i 0; i--) { swap(nums[0], nums[i]); heapify(nums, i, 0); } }这里最容易踩的两个坑一是建堆时必须从最后一个非叶子节点n/2-1开始而不是从0开始二是每次交换后堆的大小减1heapify的n参数必须传当前有效长度否则已排好的数据会被重新打乱。另外建议多嘴说一句“堆排序是不稳定排序最好别用在需要稳定性的场景”这能体现出你对工程细节的敏感度。冒泡排序如果被问到直接用“带标志位的优化版”写一旦某轮没有发生交换就提前结束复杂度最好情况能到O(n)。2.3 快速幂、Dijkstra、贪心、二分图HK与DC3这几个考点放在一起说是因为它们分别代表了算法面试中不同类型的题目数值计算、图论、组合优化、字符串处理。快速幂的核心就一句话把指数二进制拆开底数不断平方遇到二进制位为1就乘进结果。手写代码很短long long quickPow(long long a, long long b, long long mod) { long long res 1; while (b 0) { if (b 1) res res * a % mod; a a * a % mod; b 1; } return res; }Dijkstra考的是优先队列优化版本重点说清楚为什么不能用普通队列因为每个节点的最短距离会动态更新必须用优先队列每次取当前距离最小的节点复杂度O((VE)logV)。被问负权边时直接回答“Dijkstra不能处理负权边有负权边用Bellman-Ford或SPFA”。贪心算法在面试里更多是作为一种“先想想”的思路出现最多的题型是区间调度按结束时间排序和哈夫曼编码。答题时先说“greedy choice property”和“optimal substructure”再给具体策略比直接扔代码显得更有章法。二分图HKHopcroft-Karp和DC3后缀数组属于加分项考得不多但一旦考到就是区分度。HK算法核心是用BFS为每个未匹配点找增广路径的层次图再用DFS做多路增广能把二分图最大匹配复杂度从O(VE)降到O(E√V)。DC3是线性时间构造后缀数组的算法结合了基数排序和分治思想如果能把这两个算法的思路说清楚基本能给面试官留下“算法功底扎实”的印象。3. 机器学习与深度学习从经典模型到变分推断3.1 KNN的三种应用能力与聚类算法选型热词里有一条“KNN算法的应用能力包括哪三个方面”这题看起来基础但很多人答不全。KNNK近邻不是只能做分类它有三种典型应用能力分类投票决定类别、回归取K个近邻的均值作为预测值、密度估计与离群点检测距离分布异常的点。举几个业务里的例子分类对应垃圾信息识别回归对应二手房价格预测离群点检测对应刷单异常账号识别。一个算法在不同任务里换着用这比单纯背概念更能打动人。聚类算法则要会做选型对比。面试官如果问“K-Means和DBSCAN你怎么选”不要只回答“K-Means快”要把适用场景说清楚维度K-MeansDBSCAN聚类形状凸形簇任意形状类别数需要指定K不需要指定噪声处理敏感噪声会影响质心自动识别噪声点复杂度O(nkt)O(n²)可用索引优化适用场景大规模规整数据密度不均、有大量噪声的数据3.2 XGBoost与梯度提升树的高频追问XGBoost在算法面试里属于“必被追着问”的模型。面试官通常不会满足于你回答“XGBoost是GBDT的优化版本”他们想听的是目标函数和分裂增益。XGBoost目标函数的核心是[ Obj \sum_{i1}^{n} L(y_i, \hat{y}i) \sum{k1}^{K} \Omega(f_k) ]其中正则项 (\Omega(f_k) \gamma T \frac{1}{2}\lambda \sum_{j1}^{T}w_j^2)T是叶子节点数w是叶子权重。XGBoost在每轮迭代时对损失函数做二阶泰勒展开利用一阶导g和二阶导h分裂时的增益计算为[ Gain \frac{1}{2}[\frac{G_L^2}{H_L \lambda} \frac{G_R^2}{H_R \lambda} - \frac{(G_LG_R)^2}{H_LH_R\lambda}] - \gamma ]其中G和H分别是叶子节点上样本的一阶导累加和二阶导累加。能把这个公式讲清楚再补充“XGBoost相比GBDT的优势在于二阶导数、正则项、列抽样、并行化”这题的分数基本就拿到了。3.3 强化学习与KL-ELBO变分推断强化学习在这份题单里出现的频率不低。面试官想知道的是“你是否理解智能体与环境交互的学习范式”而不是让你背DQN的架构。回答时抓住三个核心要素策略Policy、奖励Reward、状态转移Transition。如果被追问深度Q网络就重点说“目标网络经验回放”两个技巧解决样本相关性和训练不稳定的问题。KL-ELBO是变分推断里的核心概念公式推导要注意逻辑链。在变分推断中我们要用分布q(z)近似后验p(z|x)直接优化KL散度KL(q||p)不可行因为里面包含log p(x)不好算。于是转化成优化ELBOEvidence Lower Bound[ \log p(x) ELBO(q) KL(q(z)||p(z|x)) ]因为KL散度非负所以log p(x) ≥ ELBO(q)。最大化ELBO等价于最小化KL(q||p)而ELBO可以写成[ ELBO(q) E_{q(z)}[\log p(x, z)] - E_{q(z)}[\log q(z)] ]面试时把这条链路讲顺了面试官就知道你是真的理解变分推断而不是背公式。3.4 图像分类算法与工业异常检测的前沿方向EVA-02这类视觉Transformer模型在热词里出现说明面试题对前沿模型也有涉及。EVA系列模型的核心思路是用大规模CLIP模型做知识蒸馏把冻结的CLIP视觉编码器的特征迁移到纯Transformer模型中训练效率远高于从零训练。回答时不需要背模型参数把“蒸馏冻结CLIP多模态对齐”这个思路说清楚就行。工业异常检测是另一个值得准备的方向。传统方法用重构误差AutoEncoder重建正常样本异常样本重建误差大现在主流方法是PatchCore这类基于特征存储库的方法用预训练网络提取正常样本的patch特征存入内存库测试时对比特征距离判断异常。面试官如果追问“为什么不直接用分类模型”就回答“异常类型未知且样本极少单分类/距离度量更实用”。4. 图像与信号处理看似偏门其实是业务刚需4.1 图像锐化的拉普拉斯算法与Sobel的区别热词里同时出现“图像锐化的拉普拉斯算法”和“sobel算法”这俩确实经常被拿来做对比。核心区别是一阶微分和二阶微分Sobel算子是边缘检测提取的是梯度幅值拉普拉斯算子是二阶微分反应的是灰度突变率的变化常用于锐化。拉普拉斯算子的3×3模板常见有两种[ \begin{bmatrix} 0 1 0 \ 1 -4 1 \ 0 1 0 \end{bmatrix} \quad \begin{bmatrix} 1 1 1 \ 1 -8 1 \ 1 1 1 \end{bmatrix} ]锐化公式一般写作 g f - c * ∇²f注意这里的∇²f用的是“中心为负”的模板比如中心-4所以是减去拉普拉斯结果如果模板中心为正则公式变成 g f c * ∇²f。这个符号问题我在面试里看很多人栽过回答时最好主动把这两种对应关系讲一下。Sobel算子的两个模板[ G_x \begin{bmatrix} -1 0 1 \ -2 0 2 \ -1 0 1 \end{bmatrix} \quad G_y \begin{bmatrix} -1 -2 -1 \ 0 0 0 \ 1 2 1 \end{bmatrix} ]梯度幅值 ( G \sqrt{G_x^2 G_y^2} )工程上常用 ( |G_x| |G_y| ) 近似。实操上最大的坑是拉普拉斯算子对噪声极其敏感直接用原图算会放大噪声所以正确流程是先高斯模糊降噪再用拉普拉斯锐化。用OpenCV实现的代码也很简单import cv2 img cv2.imread(image.jpg, cv2.IMREAD_GRAYSCALE) blur cv2.GaussianBlur(img, (3, 3), 0) lap cv2.Laplacian(blur, cv2.CV_16S, ksize3) lap cv2.convertScaleAbs(lap) sharpened cv2.subtract(img, lap) # 中心为负的模板注意用CV_16S而不是CV_8U因为卷积结果会出现负值直接存成8位会截断信息。4.2 音频重采样算法从线性插值到多相滤波音频重采样在热词里出现这道题更容易出现在偏音视频或语音的团队。重采样的本质是改变采样率比如把44.1kHz转成48kHz做不做得好直接决定音频质量。最简单的重采样算法是线性插值对相邻两个采样点做线性插值得到新采样点。优点是实现简单缺点是对高频成分的衰减明显容易产生频谱混叠。工程上使用最多的是多相滤波器Polyphase Filter预先算好一个低通滤波器系数按重采样比例拆成多个子滤波器组每个输出样本只需和其中一组系数做卷积计算量远小于直接做一次完整低通卷积。面试官如果问“重采样过程中最关键的一步是什么”答案不是插值本身而是抗混叠滤波。降采样前必须经过低通滤波器截止频率要低于新的奈奎斯特频率否则高频分量折叠到低频声音会变糊。4.3 PID、卡尔曼滤波、粒子群与模拟退火这几个属于跨领域的“元算法”面试官可能会把它放在业务问题里考。PID算法在工业控制里无处不在热词里还有一条“pid算法在crps psu power的作用”其实就是电源/控制系统里的反馈调节应用。PID的三个参数作用要能讲明白P比例根据当前误差调整输出误差越大调整越大但会产生稳态误差I积分累积历史误差消除稳态偏差D微分预测误差变化趋势抑制超调。调参口诀也记一下先调P让系统基本稳定再加I消除稳态误差最后加D抑制超调每加一项都要回到第一步重新验证。卡尔曼滤波考的更多是“懂不懂状态估计”。它由预测和更新两步组成预测是利用状态方程比如匀速运动模型预测下一步位置和误差协方差更新是利用观测值比如GPS读数加权修正权重就是卡尔曼增益K。面试时能把五个核心公式写出来就说明真懂[ \hat{x}^- A\hat{x} Bu, \quad P^- APA^T Q ] [ K P^-H^T(HP^-H^T R)^{-1} ] [ \hat{x} \hat{x}^- K(z - H\hat{x}^-), \quad P (I - KH)P^- ]粒子群和模拟退火都属于启发式优化算法。粒子群的核心是每个粒子在搜索空间里同时向个体最优pbest和全局最优gbest方向移动速度和位置更新公式[ v_{i}(t1) w v_i(t) c_1 r_1 (pbest_i - x_i) c_2 r_2 (gbest - x_i) ] [ x_i(t1) x_i(t) v_i(t1) ]w是惯性权重c1是自我认知系数c2是社会学习系数。模拟退火则要抓住Metropolis接受准则温度越高越容易接受差解随着温度降低接受差解的概率越来越小从而避免陷入局部最优。5. 业务落地与算法工程化决定offer高度的加分项5.1 规则引擎Drools的Rete算法原理与事实匹配过程这道题是工程向的硬核问题。Drools是Java生态最常用的规则引擎底层用Rete算法做规则匹配。Rete算法的核心思想是把规则编译成一个有向无环网络事实进入网络后逐层传播避免每条规则都重新匹配一遍所有事实。可以这么理解假设有100条规则每条规则里有多个条件如果每条规则都从头匹配所有事实复杂度是规则的重复劳动。Rete算法把相同的前缀条件提取出来共享把条件拆分成Alpha节点单条件匹配和Beta节点条件之间的Join也就是跨事实的关联匹配最终匹配结果汇聚到Terminal节点触发规则。事实匹配的流程大致是事实对象被插入Work Memory后首先进入Alpha网络做单条件过滤符合条件的对象进入Alpha内存然后到Beta网络和之前已经匹配的部分结果做Join产生新的部分匹配存入Beta内存当某个规则的所有条件都被满足激活进入Agenda由冲突解决策略决定执行顺序。面试时建议画一个简单的图规则“年龄30且城市北京”在网络里如何传播。能把这三个节点的关系讲清楚已经比大多数只背概念的人强了。5.2 国密算法与SSL弱哈希修复热词里有“sm2、sm3、sm4和zuc算法”这在国内互联网公司的面试里越来越常见因为很多项目需要满足信创和合规要求。这四种算法分工要记住SM2是非对称加密基于椭圆曲线替代RSASM3是密码哈希摘要256位用于数字签名和完整性校验SM4是对称分组加密128位分组、128位密钥类似AESZUC是序列密码主要用于移动通信加密。如果面试官让你比较SM4和AES从安全性、效率、国内合规三个方面说。如果问签名验签流程就重点讲SM2 SM3的组合使用。“SSL证书使用了弱HASH算法CVE-2005-4900怎么修复”这道题属于安全运维类。CVE-2005-4900指的是证书签名使用SHA-1算法的风险。修复思路分几步先检查现有证书的签名算法用OpenSSL命令查看openssl x509 -in cert.pem -text -noout | grep Signature Algorithm如果输出SHA1WithRSAEncryption就说明证书用了弱哈希。解决方法是重新生成密钥和证书签名请求用SHA-256算法签名然后把新证书配置到Nginx/Apache并重载服务。不用改业务代码但要注意证书链里所有中间证书的签名算法也要检查。5.3 BM25排序算法与搜索业务场景BM25是搜索排序里的经典相关性模型也是很多算法工程师面试的必问考点。它的核心思想是一条文档和查询的相关性由查询中每个词在文档中的词频决定同时也受词在全局文档中的稀有程度IDF影响。BM25公式[ score(D,Q) \sum_{i1}^{n} IDF(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 1)}{f(q_i, D) k_1 \cdot (1 - b b \cdot \frac{|D|}{avgdl})} ]k1控制词频饱和度b控制文档长度归一化的强度。对于58同城这类信息分类平台同一职位或房源的文本篇幅差异很大BM25的文档长度惩罚就很重要避免长文本天然得分更高。面试时如果被追问“BM25和向量检索怎么选择”回答思路是BM25适合关键词精确匹配为主的短查询可解释性强向量检索适合语义匹配和长尾改写生产环境往往混合使用BM25作为召回候选向量做语义补充最后用learning to rank融合排序。6. 面试复盘答题节奏、表达方式与避坑建议6.1 面试官想听的“思路”是什么面试和考试最大的区别在于面试官在乎的不是你会不会背这道题的答案而是你能不能把一个未知问题拆解成已知方法。建议答题时固定用“暴力解→优化解→边界解”的三层结构。举个例子如果面试官问“如何在海量日志中统计TopK的IP”别上来就写堆排序。先说暴力做法是统计所有IP频率再排序然后用哈希表统计频率、用大小为K的小顶堆维护TopK复杂度O(nlogK)再补充如果内存放不下可以哈希分片处理。这样做的好处是你给面试官提供了追问的抓手他也能看到你的思维层次。手撕代码时务必先确认输入输出的边界输入为空怎么办、全是重复值怎么办、数组长度有没有限制。这些细节往往比代码本身更影响面试评价。6.2 七个高频翻车现场这些年我在面试别人和复盘自己面试的过程中总结了一些高频翻车点这里整理成表格供大家自查挂点典型错误正确姿势KMP、next数组定义搞混用了另一种定义却不说明先确认“使用前缀函数定义”再计算堆排序建堆起点错误从0开始heapify从n/2-1开始即最后一个非叶子节点拉普拉斯锐化符号反中心为正却用gf-∇²f先确认模板中心符号再选公式Sobel与拉普拉斯混为一谈把Sobel说成锐化算子Sobel是边缘检测一阶微分拉普拉斯可锐化XGBoost和GBDT区别说不全只答“加了正则”二阶泰勒展开、正则项、列抽样、并行化逐条说Dijkstra用普通队列复杂度变成O(V²)甚至出错必须用优先队列取最小距离点BM25和TF-IDF区别模糊只说“BM25更高级”词频饱和度k1和文档长度惩罚b是核心6.3 一周冲刺复习计划如果离面试还有一周不建议再盲目刷题。我的建议是按“基础算法40% 机器学习25% 工程与业务25% 前沿与项目10%”的比例分配时间第1-2天主攻KMP、堆排序、快速幂、二分图HK、贪心题每天手写2-3遍核心代码直到不看任何提示能独立写对第3天机器学习里KNN、聚类、XGBoost、强化学习重点练习“用业务场景说算法”比如用KNN做异常登录检测第4天把Sobel、拉普拉斯、音频重采样、卡尔曼滤波过一遍用Python/OpenCV跑一遍图像和音频的处理流程第5天工程向内容集中突击Rete算法画图讲清流程、SM2/SM3/SM4/ZUC用途整理成表、BM25公式手推一遍第6天模拟面试找人给你随机抽题要求5分钟内讲思路、10分钟内写完代码训练自己的表达能力第7天复盘所有翻车点把自己最容易忘的公式和易错点写在一张A4纸上进面试前看一遍。我个人在带候选人时经常发现很多人基础算法题能AC但被问到“这个算法在你的项目里怎么用”就卡壳。从这份58同城的面试题来看面试官明显是想把“会刷题”和“会干活”区分开的。所以你在复习时每学一个算法都多问自己一句这个东西在真实业务里能解决什么问题想清楚这个问题你就不再是背答案而是真正在建立自己的算法知识体系了。
返回列表