数据结构与算法
算法题的核心不是模板名,而是契约、不变量与成本模型。先规定输入和输出含义,再找一个每轮保持成立的事实,证明结束时它推出答案;复杂度要同时计算遍历、辅助存储、调用栈和输出规模。
核心模型
算法题的核心不是模板名,而是契约、不变量与成本模型。先规定输入和输出含义,再找一个每轮保持成立的事实,证明结束时它推出答案;复杂度要同时计算遍历、辅助存储、调用栈和输出规模。
原理与机制
对象、数组与图的身份不能丢
数组扁平化用显式栈逆序压入,保持输出左到右并避开递归栈;这只适用于明确约定的稠密、无环输入。重复引用的子数组应展开两次,全局 visited 不能冒充路径上的环检测。克隆则恰好需要原对象→新对象映射:先登记空壳再处理属性,才能保留环和共享引用。空槽、Symbol、访问器和原型都是独立契约,JSON 往返无法保真;复制描述符和读取 getter 的值也不同。
映射把全表搜索变成局部操作
列表转森林先建立 id 映射,再连接父子,不要求父先于子;重复 ID、缺父与环分别诊断。在每个非根恰有一个合法父节点的前提下,从全部根可达数量不足可识别环及其附属节点,该结论不能推广到任意图。LRU 则利用 Map 插入顺序:命中或更新时 delete 后 set,淘汰最前键;has 与 get 是否刷新应写清。TTL 判断是否过期,LRU 判断容量不足时先扔谁,按条数限额还不等于内存限额。
搜索正确性来自不变量
无权图 BFS 按距离层扩展,首次发现即记录前驱并入队,可防同层重复;数组加 head 游标避免反复 shift。首次发现路径的边数最短,代价 O(V+E),若要枚举全部最短路径,还需多个前驱且计算输出规模。二分查找则保持左侧都小于 target、右侧都不小于 target 的区间不变量。每步排除确定的一半,区间为空时收敛到插入位置;未排序、NaN 或比较器不一致会破坏证明前提。
排序后扫描与分治有不同证据
闭区间合并先复制端点并按起点排序,再维护最后合并段;相等端点相交,半开语义要另定。归并排序从有序小段两指针合成大段,每层总工作 O(n),段长翻倍共 O(log n) 层;相等时先取左段保证稳定,复用辅助数组仍需 O(n) 空间。现代原生 sort 要求稳定,但标准不强制特定算法或复杂度。复制外层数组不会深拷贝对象,比较器成本也未必恒定。
状态递推与标准解析各自减少歧义
无限硬币最少枚数令 dp[s] 表示金额 s 的最优值,dp[0]=0。枚举最后一枚正面额 c,取 dp[s-c]+1 的最小值;若子方案不最优,替换后会改进原方案,因此递推成立。时间 O(金额×面额数)、空间 O(金额),是按数值展开的伪多项式算法。URL 则优先使用标准解析器而非手拆:保留重复键,区分空值与缺失,按白名单验证数值和跳转目的地。Map 能避开原型键冲突,但不会自动提供授权。
最小示例
javascript相等时仍收缩右边界,所以重复的2得到第一个位置。答案允许等于数组长度,右开区间不会漏掉插入末尾的情况。函数假设输入已按有限数字升序排列,复杂度 O(log n);若先验排序,不能把整个流程也说成 O(log n)。
核验:Node v24.19.0:空数组、重复值首位置、末端插入和全大于目标断言通过;未验证未排序或非法数值输入。
边界与取舍
边界
- 面额1、3、4凑6时,贪心为三枚,最优是3+3;零或负面额会破坏递推的先后依赖。
- BFS 最短指无权图的边数最少;带权图不能直接沿用首次发现结论。
- Map 常见哈希实现近似常数访问,但 ECMAScript 只要求平均次线性,不能声称规范保证严格 O(1)。
取舍
- 显式栈消除调用栈限制,却仍要付出工作栈与输出内存;极大输入应考虑分段或流式输出。
- 保留引用身份忠于原图,深度隔离值则可能改变语义;先定义数据契约,再决定复制范围。
口述示范
我会先澄清数据、边界和输出,再讲不变量与终止条件,最后分开分析算法成本和语言运行时成本。用重复、空值、环和反例验证契约,比只背一段代码更可靠。
章节练习
参考来源与核验边界
- MDN:Map · 核验 2026-10-04
- Princeton Algorithms:Mergesort · 核验 2026-10-04
- MIT 6.006:算法讲义 · 核验 2026-10-04
- MDN:URLSearchParams · 核验 2026-10-04
2026-10-04 核验。算法证明在本章输入契约内成立;硬币题契约和归并实现均属教学延伸,不能据企业面经主题推断现场完整题面。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。