![]()
北美大厂算法面试有个公开的秘密:有人刷了400题挂掉Google,有人只练80题拿到5个offer。差距不在题量,在是否提前看过"考纲"。
LeetCode现存3000+题目,但面试高频考点高度收敛。前Google工程师、现Meta技术面试官整理了一份内部流传的模式清单——14个代码模板,覆盖95%的面试题型。这不是投机取巧,是把O(n²)的暴力解法压缩成O(n)的系统工程。
双指针:从两头往中间夹
数组或字符串里找配对、比大小、做分割,第一反应应该是双指针。left从0出发,right从末尾往回走,每次循环干掉一半搜索空间。
经典场景:Two Sum(有序数组版)、盛最多水的容器、验证回文串、三数之和。模板核心就五行——初始化、循环、比较、收缩左边界、收缩右边界。
关键认知:双指针的本质是用空间换时间的反向操作。不建哈希表,用两个游标消除内层循环,把平方复杂度压成线性。
一个细节:三数之和的去重逻辑容易写错。排序后,当left右移时如果下一个数和当前相同,要跳过;right同理。这个去重比算法本身更容易挂面试。
滑动窗口:子数组问题的通用框架
求"满足某条件的连续子数组",比如最大和、最长无重复字符、最小覆盖子串——全是滑动窗口的领地。
模板分两种。固定窗口大小:右边进一个,左边出一个,保持窗口恒定。可变窗口:右边一直扩,直到违反约束,再从左边收缩到合法。
代码骨架是四层嵌套:外层遍历右边界、更新窗口状态、内层while收缩左边界、更新结果。窗口状态通常用哈希表或数组计数,面试时先写伪代码确认面试官要的是固定还是可变。
高频翻车点:Minimum Window Substring要求覆盖所有目标字符,不是任意k个。很多候选人把"至少k个不同字符"和"覆盖目标串"搞混,20分钟直接归零。
快慢指针:链表问题的作弊器
链表没法随机访问,但快慢指针给了你一个"伪二分"的能力。slow走一步,fast走两步,fast到终点时slow正好在中点。
判环、找中点、检测快乐数,同一个模板改两行就能用。判环时相遇即存在环;找中点时返回slow;快乐数把数字替换成各位平方和,重复即环。
Meta去年秋招的follow-up:如果链表有环,找到环的入口点。这需要数学推导——相遇后把slow拉回head,同步走再次相遇即为入口。能现场推出来的,评级直接升一档。
区间合并:日程表冲突的标准解法
会议室预定、日程合并、区间插入,本质都是同一道题:先按起点排序,然后遍历,要么合并(当前起点≤上一个终点),要么新开区间。
Meeting Rooms II的变种问"最多需要几间会议室"——用最小堆存每个会议的结束时间,新会议开始时间≥堆顶则复用房间,否则开新房间。堆的大小就是答案。
这个模式在Google面试出现频率极高,因为和实际系统设计的负载均衡问题同源。能讲出"这相当于找最大并发数"的候选人,会被标记为"有系统思维"。
![]()
循环排序:原地排序的野路子
数组数值范围在1到n之间,要求O(n)时间、O(1)空间——循环排序是唯一解。把每个数放到它该去的位置(nums[i]应该放在索引nums[i]-1处),放不下的就是缺失或重复的。
Find the Missing Number、Find the Duplicate Number、Find All Duplicates,全是这个套路。代码模板是while循环:当前数不在正确位置,就和正确位置的数交换。
易错点:交换后不能i++,要继续检查换过来的数。很多人惯性写i++,漏掉连锁反应,调试半小时。
链表反转:递归迭代的两种人格
反转链表是面试的"hello world",但follow-up能无限深挖。K个一组反转、部分反转、两两交换,全是同一模板的变体。
迭代版:三个指针prev、curr、next,逐节点后移。递归版:递归到末尾,返回时逐个翻转指向。递归版代码更短,但空间O(n),面试官会问能不能优化。
Amazon的变态考法:用O(1)空间反转m到n之间的部分。需要先用双指针走到m-1位置,再套用标准反转模板,最后拼接三段。能一次写对的,近两年内见过的不超过10个。
树的双遍历:前序+中序/后序重建
给两种遍历序列重建二叉树,是考察递归思维的试金石。前序+中序、后序+中序可以唯一确定树,前序+后序不行(除非满二叉树)。
模板核心:前序/后序的第一个/最后一个元素是根,在中序里找到根的位置,左边是左子树,右边是右子树。递归构建,用哈希表存中序索引避免重复扫描。
时间复杂度O(n),空间O(n)存哈希表。面试官常问的优化:如果数组很大,能不能流式处理?答案是只能预处理,因为必须知道左右子树的边界才能递归。
层级遍历:BFS的队列美学
树的按层打印、找最浅叶子、连接同层节点,全是BFS的领地。用队列,每层记录size,内层循环处理完当前层再进下一层。
Binary Tree Level Order Traversal的变形:之字形打印、找每行最大值、判断完全二叉树。模板不变,变的是内层循环里对节点的操作。
Google的陷阱题:用DFS实现层级遍历。需要记录深度,按深度把节点塞进结果数组的对应位置。能切换两种思路的,说明理解了遍历的本质区别。
子集模式:回溯的暴力美学
求所有子集、排列、组合,回溯是通用解。模板是递归函数里:做选择、递归、撤销选择。子集问题选或不选当前元素,排列问题选哪个位置放当前元素。
去重是难点。有重复元素时,先排序,然后跳过同一层已经用过的相同元素。这个"同一层"和"同一支"的区别,90%的候选人讲不清楚。
Subset Sum问是否存在和为target的子集,可以用回溯剪枝,也可以用动态规划。面试时先问数据范围,n≤20用回溯,n≥100必须用DP,选错直接超时。
![]()
二分变种:找边界、找旋转、找答案
二分查找不只是找目标值。找第一个≥target的位置、找最后一个≤target的位置、找旋转数组的最小值、找峰值元素——全是二分模板的变形。
核心不变:确定搜索区间[left, right]还是[left, right),确定中间点比较后收缩哪边,确定终止条件和返回值。旋转数组的关键是判断哪半边有序,然后在有序半边判断target是否在范围内。
Search in Rotated Sorted Array的follow-up:有重复元素怎么办?最坏情况退化成O(n),但平均还是O(log n)。能分析出这个的,算法基础分拿满。
拓扑排序:有向图的依赖解析
课程表、编译顺序、任务调度,全是拓扑排序。Kahn算法(BFS)或DFS记录后序遍历,两种实现都要会。
Kahn算法:计算入度,入度为0的入队,逐个弹出并减少邻居入度。DFS版:递归访问所有邻居,访问完把当前节点压栈,最后逆序就是拓扑序。
检测环是隐藏考点。Kahn算法最后如果还有节点没访问,说明有环;DFS版用三色标记(未访问/访问中/已访问),遇到访问中节点即环。
并查集:连通性的O(α(n))解法
朋友圈、省份数量、冗余连接、岛屿数量II——动态连通性问题,并查集是标准答案。路径压缩+按秩合并,时间复杂度接近常数。
模板四件套:find(带路径压缩)、union(按秩合并)、初始化、计数。面试时先写朴素版,面试官要求优化再补上压缩和合并。
LeetCode 305岛屿数量II的trick:从全是水的网格逐步添加陆地,每添加一个检查四邻居,用并查集维护连通分量数。能想到并查集的,已经跑赢80%的候选人。
前缀和:子数组求和的降维打击
求和为k的子数组个数、和为k的最大长度、二维区域和检索——前缀和把区间查询变成O(1)。
一维:presum[i] = sum(nums[0..i-1]),区间和= presum[j+1] - presum[i]。二维:presum[i][j]存左上角(0,0)到(i-1,j-1)的和,容斥原理算任意矩形。
和为k的子数组个数,用哈希表存前缀和出现次数,当前前缀和-k的次数就是以当前结尾的合法子数组数。这个"当前-目标=历史"的思路,和两数之和的哈希表解法同源。
动态规划:最后一块拼图
DP是独立大类,但面试高频的其实就几种:线性DP(爬楼梯、打家劫舍)、区间DP(石子合并、最长回文子序列)、背包DP(01背包、完全背包)、树形DP(打家劫舍III)、状态压缩DP(旅行商问题,极少考)。
线性DP的模板:dp[i]表示以i结尾的最优解,状态转移看i-1、i-2或某个前缀。背包问题的模板:二维dp[i][j]表示前i个物品容量j的最大价值,优化成一维要倒序遍历容量。
面试技巧:先写暴力递归,加记忆化,再改迭代。这个过程展示思维路径,比直接写DP得分更高。
这14个模式不是终点。真正的高手会在模板基础上变形——双指针扩展到多指针,滑动窗口加上单调队列,BFS换成双向BFS。但变形的前提是模板已经刻进肌肉记忆。
一个数据点:2024年北美大厂算法面试中,这14个模式的原题或变体出现频率超过90%。剩下的10%是设计题或罕见题型,不影响hire/no hire的决定。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.