研发工程师面试宝典 - 第4节

第4章 技术基础问答:数据结构与算法高频题、复杂度分析、手写代码规范

本章定位: 数据结构与算法(DSA)是大厂研发面试的“基本盘”,本章覆盖三大核心:高频题型解法、时空复杂度权衡、手写代码规范。目标是帮助面试者在15分钟内展示出清晰的解题思路和扎实的编码功底。

知识结构:高频考点分类

类别代表结构/算法核心指标面试频次
线性结构数组、链表、栈、队列随机访问 vs 增删效率⭐⭐⭐⭐⭐
树形结构二叉树、BST、堆、Trie递归/迭代、层级关系⭐⭐⭐⭐⭐
图算法BFS/DFS、拓扑排序、最短路径遍历顺序、状态标记⭐⭐⭐⭐
动态规划背包、子序列、区间DP状态定义、转移方程⭐⭐⭐⭐
复杂度分析大O表示法、均摊分析时间/空间、数据规模⭐⭐⭐⭐⭐
明确边界约束 扩展基础解法 瓶颈分析:空间换时间 手写规范 & 边界测试 第1步 · 理解题意 第2步 · 暴力解法 第3步 · 分析瓶颈 第4步 · 数据结构优化 第5步 · 手写代码测试

📌 面试问答 1:数组 vs 链表

面试问题:请详细对比数组和链表的区别,并结合工程场景说明选型依据。

  • 面试官考察点:基础数据结构特性掌握、复杂度分析、工程权衡能力。
  • 回答框架: 存储结构 → 随机访问性能 → 增删性能 → 缓存局部性 → 工程场景映射。
  • 示例回答:“数组连续内存,支持O(1)随机访问,但中间增删需移动元素(O(n));链表离散存储,支持O(1)插入/删除(已知节点),但随机访问需遍历(O(n))。Java中ArrayList封装数组,适用读多写少(如日志存储);LinkedList封装链表,适用写多读少(如消息队列)。”
  • 可能追问:“CPU缓存行如何影响数组遍历性能?”“HashMap的数组开链结构结合了哪些优势?”
⚠️ 避坑提醒:不要只背区别,一定要落到时间复杂度分析和具体工程场景(如MySQL B+树 vs Redis 链表)。

📌 面试问答 2:手写 LRU 缓存淘汰算法

面试问题:请设计和实现一个最近最少使用(LRU)缓存,要求get和put操作时间复杂度为O(1)。

  • 面试官考察点:数据结构组合设计能力、手写代码边界控制、时空复杂度意识。
  • 回答框架: 选型(HashMap+双向链表) → 核心API(get/put) → 复杂度分析 → 手写代码(注意头尾哨兵节点)。
  • 示例回答:“采用HashMap + 双向链表。Map提供O(1)查询,链表维护访问顺序。get时若存在则移至头部;put时若key存在则更新值并移至头部,不存在则创建新节点插入头部,若容量超限则删除尾部节点。Java的LinkedHashMap正是基于此实现,需注意重写removeEldestEntry方法。”
  • 可能追问:“为什么必须用双向链表而不是单向?”“如何实现线程安全的版本(ConcurrentHashMap + 锁)?”
⚠️ 避坑提醒:画图时漏掉头尾指针更新;写代码时忘记容量淘汰逻辑;面试中应先说思路再编码,保持沟通。

📌 面试问答 3:两数之和(代码规范专项)

面试问题:给定整数数组 nums 和整数目标值 target,请返回和为目标值的两个数的数组下标。

  • 面试官考察点:思维推导过程(暴力→优化)、哈希表运用、变量命名规范、边界条件处理。
  • 回答框架: 暴力解 → 瓶颈分析 → 哈希优化 → 手写代码(含空值判断) → 测试用例。
  • 示例回答:“暴力两层循环时间复杂度O(n²),可优化为哈希表。遍历数组,检查target - nums[i]是否在map中,在则返回索引,否则写入map。编码时注意参数校验和变量命名,如用numToIndexMap命名map,增强代码可读性。整体时间复杂度O(n),空间复杂度O(n)。”
  • 可能追问:“如果数组是升序排列的,如何进一步优化?”(双指针O(n),空间O(1))
⚠️ 避坑提醒:不要直接抛出最优解。必须先从暴力解推导,体现优化思维。手写代码注意命名规范(禁用拼音/单字母变量)。

项目案例章:技术基础项目表达模板

项目表达STAR模型:实时排行榜系统 S 情境背景 电商大促 / 游戏赛季末 高并发读写请求 T 目标任务 实时全服排名计算 延迟要求 p99 < 100ms A 核心行动 选型 Redis Sorted Set 分层排名 + 异步持久化 R 量化结果 支撑 QPS 1.2w 千万级用户稳定运行

📦 项目名称:分布式毫秒级实时排行榜系统

维度内容
业务背景电商618/双11大促大屏,或游戏S级赛季结算,需实时展示全服积分Top 100排行榜。
规模指标用户数1000万+,DAU 500万+,写QPS峰值1.2万+,读QPS峰值5万+。
技术栈Redis(Sorted Set / ZSET)、Spring Boot、MySQL、Kafka。
核心难点
  • 海量数据实时排序,传统DB order by 不可行。
  • 热点Key问题(Top 100被高频读取)。
  • 数据一致性(缓存与DB同步)与持久化保证。
面试高频追问
  • Q:为什么选择Redis ZSET?底层实现是什么?A:底层基于跳表 + 哈希表,插入和排序时间复杂度O(log n)。
  • Q:内存放不下所有用户数据怎么办?A:采用分桶排名 + 近似排名策略,热数据在Redis,全量数据离线计算。
  • Q:如何保证排名强一致性?A:业务上接受最终一致性,通过消息队列异步回写DB,关键时刻人工降级。
💡 可迁移回答话术:“在面临海量数据实时排序的挑战时,我放弃了传统数据库的全表扫描方案,选用了Redis Sorted Set作为核心排序引擎,其跳表结构保证了稳定高效的排序性能。针对千万级用户,我们采用了‘分层排名’架构:热榜数据在Redis缓存,全量排名通过离线任务异步计算,兼顾了实时性和资源成本。这一方案可平滑迁移到实时热点新闻、直播礼物榜、在线游戏积分赛等通用业务场景。”