资讯动态

程序员面试技术爆款文:2026大厂算法通关手册——从零基础到LeetCode刷穿,这一篇就够了

发布时间:2026/10/13 16:34:53 来源:尧图企业网站定制
面试造火箭入职拧螺丝别慌吃透这份数据结构与算法指南你也能轻松拿下技术面试一、写在前面为什么算法成了程序员的“高考”在2026年的今天如果你去参加任何一家互联网公司的技术面试无论是字节、腾讯、阿里还是美团、拼多多、小红书算法题几乎是必考项。很多刚入行的朋友会问“我平时写业务代码增删改查调接口几乎用不到红黑树、动态规划为什么面试非要考这些”道理其实很简单——面试官想看的不是你会不会背某个题的答案而是你能不能像计算机一样思考问题。数据结构决定你怎么“存东西”算法决定你怎么“找东西、改东西”。一个不懂算法的人写出来的代码可能在小数据量时毫无问题一旦数据量大了程序就可能慢到崩溃、内存爆炸。所以这一篇文章我会用最通俗的语言、最生活化的例子把面试中最常考的数据结构与算法知识从头到尾给你讲透。全文没有复杂的数学公式只有你能听懂的故事和代码思路。放心不怕长就怕你没耐心看完。二、数据结构基础篇——数据就像积木怎么摆很重要1. 什么是数据结构从你的书包说起我们先抛开那些生硬的教科书定义。想象你每天早上背书包去上学上班。你的书包里可能会有课本、笔记本、笔袋、水杯、充电宝、钥匙、纸巾……如果你把这些东西随手乱塞那么想找一支笔的时候你可能需要翻遍整个书包翻五分钟也找不到。这叫“糟糕的数据结构”。如果你把书放一层、笔袋放外层小兜、纸巾放侧兜、充电宝放电脑夹层那么你要拿水杯时只要伸手就能摸到侧兜。这叫“好的数据结构”。在编程世界里数据结构就是“数据在计算机里的摆放方式和存取规则”。一个好的数据结构可以让程序运行飞快一个差的数据结构可能让程序慢到怀疑人生。Python里的list列表是一种数据结构Java里的ArrayList、HashMap也是一种数据结构就连最简单的变量int a 5其实也是数据结构的一部分所以不要被“数据结构”四个字吓到——你每天都在用只是不知道它叫这个名字罢了。2. 逻辑结构与物理结构——你看到的样子 vs 内存里的真样子数据有“两张脸”。一张是逻辑结构也就是你脑海里“理想中的样子”另一张是物理结构也就是计算机内存里“真实存储的样子”。逻辑结构只关心数据之间的关系不关心它们在内存里到底怎么放的。它分两大类线性结构数据排成一条线像排队买奶茶。每个元素前面最多一个人、后面最多一个人。比如数组、链表、栈、队列。非线性结构数据不止一条线比如树家谱、图朋友圈关系。一个元素可以连着好多个其他元素。物理结构只有两种形式连续存储像大学宿舍楼的房间号是连续的101、102、103……你住102我住103中间没有空房间。在内存里就是一块连续的区域比如数组。链式存储像快递柜的包裹每一个包裹上贴着“下一个包裹的柜号”你根据纸条去找下一个。在内存里不连续靠“指针”串起来比如链表。生活的例子逻辑结构是你的购物清单苹果、香蕉、牛奶你只关心顺序物理结构是你把这些东西真的放进冰箱还是放在餐桌上——冰箱里是连续的区域餐桌上可能每个东西之间有空隙。3. 数组和链表的“爱恨情仇”——一个快在“找”一个快在“改”数组和链表是面试中最常被对比的两个数据结构。它们就像高铁和公交车——高铁车厢是连在一起的连续你可以快速走到任意一节车厢随机访问公交车的站点是分散的不连续你要去某个站必须从前门开始一站一站过顺序访问。数组内存里是一整块连续空间像一排连着的抽屉每个抽屉有编号下标0,1,2…。你想拿第5个抽屉里的东西只要计算“起始地址 5 × 每个抽屉大小”一步就到速度极快——时间复杂度 O(1)。但是如果你想在中间插入一个新的抽屉那后面所有的抽屉都要往后挪一个位置挪的时候还要腾出空间非常慢——时间复杂度 O(n)。数组的大小一开始就固定了如果想装更多东西必须重新找一块更大的连续空间把原来的全部搬过去成本很高。链表内存里是分散的一个个小房间每个房间里除了存数据还存了一张“路条”上面写着下一个房间的地址。你要找某个房间只能从第一个房间开始跟着路条一个个找下去最坏情况全部找一遍——时间复杂度 O(n)。但是如果你想在中间插入一个新房间只需要改两条路条让前一个房间的路条指向新房间新房间的路条指向后一个房间。不需要搬动任何其他东西——时间复杂度 O(1)前提是你已经知道插入的位置。链表的大小可以随时改变想加就加想删就删非常灵活。一句话帮你记住区别数组是“查得快改得慢”链表是“改得快查得慢”。什么时候用数组数据量固定不常增删但经常要按位置随机访问。例子一年的每日气温记录365个浮点数每天取第i天的温度。什么时候用链表数据量动态变化频繁在中间插入和删除几乎不按位置随机访问。例子音乐播放器的“下一首”列表、LRU缓存淘汰算法的底层。三、常用数据结构逐个击破——栈、队列、哈希表、树、图1. 栈Stack——后进先出的“叠盘子”栈是一个很简单的结构就一句话后进先出LIFOLast In First Out。最后放进去的东西最先被拿出来。生活中到处都是栈的例子食堂里叠起来的餐盘你洗好一个盘子叠在最上面别人拿盘子也是从最上面拿。浏览器的后退按钮你依次访问 A → B → C点后退时先回到B再点后退回到A。编程中函数的调用函数A调函数B函数B调函数C执行完C后回到B执行完B后回到A。栈的操作只有两个核心动作push压栈把一个元素放到栈顶。pop弹栈把栈顶的元素取出来。面试必考的应用括号匹配LeetCode 20。比如 ([{}]) 是有效的([)] 是无效的。解法就是用栈遇到左括号就压栈遇到右括号就弹出栈顶看看是不是匹配的一对。小贴士很多编程语言的函数调用栈如果无限递归就会“栈溢出”也就是栈的空间被撑爆了。你肯定见过 RecursionError: maximum recursion depth exceeded那就是栈在喊救命。2. 队列Queue——先进先出的“排队”队列和栈刚好相反它是先进先出FIFOFirst In First Out。先来的先服务后来的排后面。生活的例子奶茶店排队先来的人先买到奶茶后来的人只能在后面等。打印机任务队列你先提交的文档先打印后提交的排在后。消息队列比如Kafka、RabbitMQ生产者把消息放到队尾消费者从队头取消息。队列的操作enqueue入队把元素放到队尾。dequeue出队从队头取出元素。面试中的应用广度优先搜索BFS。在走迷宫、找最短路径的时候BFS利用队列一层一层地向外探索。扩展双端队列Deque允许在两端都进行插入和删除。Python里的collections.deque就是这种结构。3. 哈希表——传说中的“O(1)查找神器”如果说数据结构里有“一招鲜吃遍天”的冠军那一定是哈希表。哈希表Hash Table也叫字典、映射可以在平均 O(1) 的时间复杂度内完成插入、删除、查找。这是什么概念无论你的数据是100条还是一亿条哈希表查找某个键的时间几乎是一样的不会变慢——除非发生了严重的哈希冲突。哈希表是怎么工作的核心就三步你有一个键比如 张三和一个值比如 95分。哈希表用一个哈希函数把键转换成一个整数比如把“张三”转成 4827371。对这个整数取模比如数组长度是1004827371 % 100 71就把键值对放到数组下标为71的位置。当你下次查找 张三 时同样的哈希函数算出71直接去下标71取数据——一步到位不需要遍历。什么是哈希冲突如果另一个键 张四 经过哈希函数后取模也算出来71那就会和“张三”抢同一个位置这就是冲突。解决冲突最常用的两种方法方法解释示意图比喻链地址法数组的每个位置不存一个元素而存一个链表。冲突的元素都挂在这个链表上。就像酒店的一个房间号对应多个客人大家共享一张大床但用链子串起来开放寻址法如果71被占了就去72看72也被占了就去73……直到找到空位。就像停车场找车位第一个车位被占了就往后开到下一个哈希表的缺点键的顺序是乱的不能有序遍历。如果哈希函数设计得不好或负载因子过高性能会急剧下降。面试常考设计一个LRU缓存LeetCode 146就是哈希表双向链表的组合。4. 二叉搜索树BST——自带排序功能的树二叉树是每个节点最多有两个孩子左孩子、右孩子。二叉搜索树是在二叉树的基础上加了一个规则对于任意节点左子树上所有节点的值都小于这个节点的值右子树上所有节点的值都大于这个节点的值。这个规则带来一个巨大的好处中序遍历的结果就是从小到大排序好的数组。查找的过程比如你要找42从根开始。如果根是504250 → 去左子树左子节点是304230 → 去右子树右子节点刚好是42 → 找到了。每一步排除一半数据非常快平均时间 O(log n)。插入的过程和查找类似一直比较大小直到遇到空的位置就把新节点放进去。删除的过程分三种情况面试常考。情况节点特点删除方式情况1叶子节点没有孩子直接删除让父节点指向空情况2只有一个孩子左或右让这个孩子“接替”自己的位置情况3有两个孩子找到右子树中最小的节点或者左子树中最大的节点用它替换当前节点再删除那个最小节点二叉搜索树有什么坑如果你按顺序插入1,2,3,4,5,6那么这棵树会变成一根“直棍”查找退化成链表时间复杂度变成O(n)。为了应对这种情况实际工程中常用平衡二叉搜索树比如红黑树Java的TreeMap、AVL树。5. 图——朋友圈就是一张大网图是比树更复杂的数据结构。树不能有环图可以有树有根图不一定有根。生活中到处都是图你的微信好友关系、地铁线路图、网页之间的超链接、知识图谱……图的存储主要有两种方式邻接矩阵和邻接表。存储方式怎么存优点缺点适用场景邻接矩阵一个n×n的二维数组arr[i][j]1表示i到j有边判断两个点是否有边O(1)占用n²空间边少时浪费稠密图边数接近n²邻接表每个节点后面挂一个列表里面是与它相连的节点只存实际存在的边省空间判断两个点是否有边可能O(n)稀疏图边数远小于n²面试中常考的图算法深度优先搜索DFS、广度优先搜索BFS、最短路径Dijkstra、拓扑排序、并查集。四、算法分析基础——如何评价一个算法的好坏1. 算法的五大特性——缺一不可一个算法不是随便写几行代码就算的。必须同时满足有输入算法可以没有输入比如输出固定字符串但一般都会有。有输出算法必须输出结果不能黑箱操作。有穷性必须在有限的步骤内结束不能无限循环。确定性每一步都应该是明确的没有“大概”、“也许”这种二义性。可行性每一步都可以通过有限的、基本的操作实现。反例while True: print(hello) 不是算法因为它不满足有穷性。2. 时间复杂度——程序到底有多快时间复杂度不是指程序跑了多少秒因为秒数和机器性能有关而是指基本操作次数随输入规模n的增长趋势。我们用大O表示法来写时间复杂度只保留增长最快的项忽略常数和低阶项。常见的大O复杂度大O表示名字例子当n1000时的操作量O(1)常数阶数组访问、哈希表查找约1次O(log n)对数阶二分查找约10次O(n)线性阶遍历数组、简单查找1000次O(n log n)线性对数阶归并排序、快速排序约7000次O(n²)平方阶冒泡排序、双层循环1,000,000次O(2ⁿ)指数阶递归求斐波那契不优化天文数字O(n!)阶乘阶全排列超天文数字复杂度排序O(1)O(log⁡n)O(n)O(nlog⁡n)O(n2)O(2n)O(n!)O(1)O(logn)O(n)O(nlogn)O(n2)O(2n)O(n!)记住如果面试官问“能不能优化”往往意味着你的时间复杂度太高需要从O(n²)降到O(n log n)或者更低。3. 空间复杂度——程序吃了多少内存空间复杂度衡量算法运行过程中占用的额外内存不包括输入本身占用的空间。O(1) 空间只用了几个固定变量比如 int i, int max。O(n) 空间用了一个大小为n的数组或者递归深度为n。O(n²) 空间用了n×n的二维矩阵。空间换时间是一个常见策略用更多内存存储中间计算结果避免重复计算。典型的例子是动态规划中的备忘录memoization。五、经典算法思想——分治、动态规划、贪心、回溯面试中光知道数据结构还不够你还需要掌握几种核心的算法思想就像武学里的“流派”。1. 二分查找——最简单的分治思想二分查找本身不复杂但它背后的分治思想是很多复杂算法的基础。二分查找的条件序列必须有序升序或降序。工作流程取中间位置 mid (left right) // 2。如果 nums[mid] target返回 mid。如果 target nums[mid]说明目标在左半边right mid - 1。如果 target nums[mid]说明目标在右半边left mid 1。重复直到 left right没找到就返回 -1。时间复杂度O(log n)因为每一轮把搜索范围砍一半。生活中的应用你翻一本500页的词典找“算法”这个词你不会从第1页开始翻你会先翻到中间看首字母在“算”之前还是之后然后继续折半——这就是二分查找。2. 分治——大事化小小事化了分治策略将一个复杂的大问题分解成若干个规模较小、相互独立、且与原问题形式相同的子问题递归地求解子问题最后合并子问题的解得到原问题的解。经典案例归并排序Merge Sort归并排序的思路分解把数组从中间分成两半。递归对左半部分排序对右半部分排序。合并将两个有序数组合并成一个有序数组。归并排序的时间复杂度稳定在 O(n log n)但需要 O(n) 的额外空间。3. 动态规划DP——记住过去推演未来动态规划和分治很像区别在于分治的子问题是独立的动态规划的子问题是重叠的。动态规划的核心三板斧定义状态dp[i] 代表什么找到状态转移方程dp[i] 和 dp[i-1] 等的关系确定初始条件和边界经典案例1爬楼梯LeetCode 70问题爬n阶楼梯每次可以爬1阶或2阶问有多少种不同的爬法。分析爬到第1阶只有1种方案爬1阶→ dp[1] 1爬到第2阶有2种方案11 或 2→ dp[2] 2爬到第3阶可以从第2阶爬1阶过来也可以从第1阶爬2阶过来所以 dp[3] dp[2] dp[1] 3通式dp[i] dp[i-1] dp[i-2]这就是斐波那契数列。用动态规划可以避免重复计算时间复杂度 O(n)空间可以优化到 O(1)。经典案例2最大子数组和LeetCode 53问题给定数组找出一段连续子数组使其和最大。思路定义 dp[i] 为以第i个元素结尾的最大子数组和。如果 dp[i-1] 是正数就加上当前元素dp[i] dp[i-1] nums[i]如果 dp[i-1] 是负数或0就不如从当前元素重新开始dp[i] nums[i]所以 dp[i] max(dp[i-1] nums[i], nums[i])最后答案是所有 dp[i] 中的最大值。4. 贪心——目光短浅但有时反而最优贪心算法每一步都采取当前状态下最好或最优的选择希望这样能导致全局最优。贪心算法的条件贪心选择性质局部最优可以导出全局最优最优子结构大问题的最优解包含子问题的最优解经典案例分发糖果每个孩子至少一颗糖评分高的孩子必须比相邻的孩子拿得多。求最少需要多少颗糖。贪心解法先从左到右遍历保证右边评分高的孩子比左边多再从右到左遍历保证左边评分高的孩子比右边多。两次贪心得到最终结果。注意不是所有问题都能用贪心。比如找零钱问题如果面额是1、3、4想凑6元贪心取411会得3张但最优解是332张。所以贪心必须证明可行性才能用。5. 回溯——试错后悔药回溯法本质上是一种穷举法它通过不断尝试如果发现当前选择不可能得到可行解就撤销上一步回溯换另一种选择继续尝试。回溯的通用模板def backtrack(路径, 选择列表): if 满足结束条件: 记录结果 return for 选择 in 选择列表: 做选择 backtrack(新路径, 新选择列表) 撤销选择回溯经典案例N皇后问题在一个n×n的棋盘上放n个皇后使得它们不能互相攻击任意两个皇后不能在同一行、同一列、同一斜线上。解法逐行放置皇后。每行尝试每一列检查是否与之前放置的皇后冲突。如果冲突就回溯到上一行换一列再试。回溯的时间复杂度很高通常是指数级但可以通过“剪枝”优化——提前排除明显不可能的情况。六、面试高频力扣题三步拆解——从读题到写代码1. 有效括号LeetCode 20题目回顾给定一个字符串只包含 (、)、{、}、[、]判断括号匹配是否合法。思路栈法遇到左括号时把对应的右括号压入栈方便后面匹配。遇到右括号时弹出栈顶元素比较是否相同。如果栈为空或弹出的不匹配说明无效。遍历完字符串后如果栈为空则所有括号都匹配了。为什么用栈因为括号的嵌套结构天然具有“后开先闭”的特性与栈的后进先出完美契合。举例([{}])遇到 ( 压入 )遇到 [ 压入 ]遇到 { 压入 }遇到 } 弹出 } → 匹配遇到 ] 弹出 ] → 匹配遇到 ) 弹出 ) → 匹配栈空有效。复杂度和边界时间 O(n)空间 O(n)最坏全是左括号。2. 爬楼梯LeetCode 70题目回顾爬n阶楼梯每次1或2阶求不同爬法数。思路动态规划状态定义dp[i] 表示爬到第i阶的方法数。转移方程dp[i] dp[i-1] dp[i-2]初始条件dp[1] 1, dp[2] 2注意n0时返回1题目一般n1但有的版本0阶是一种答案dp[n]优化空间因为 dp[i] 只依赖于前两个状态可以用两个变量滚动空间O(1)。拓展如果把“一次能爬1、2、m阶”呢那就变成 dp[i] dp[i-1] dp[i-2] ... dp[i-m]类似完全背包。3. 最大子数组和LeetCode 53题目回顾找出整数数组中和最大的连续子数组返回最大和。思路动态规划 贪心混合定义 cur 为以当前元素结尾的最大子数组和。如果 cur 是负数那加上当前元素只会更小不如直接从当前元素重新开始。即 cur max(nums[i], cur nums[i])。用 best 记录全局最大值。原始暴力法枚举所有子数组O(n²) 或 O(n³)不可取。分治法分成左右和跨越中间三种情况O(n log n)。动态规划O(n) 最优。一个易混淆点最大子数组和有负数的情况不能直接忽略负数。例如 [-2, 1, -3, 4, -1, 2, 1, -5, 4] 的最大子数组是 [4,-1,2,1] 和6。七、刷题方法论——聪明人的“刻意练习”有很多人刷了几百道题面试还是挂了为什么因为他做了“假努力”——只追求数量不重质量。1. 刷题的三个误区误区一只刷不总结刷了100道题但没有整理过笔记、没有总结过同类题型的套路。遇到变形题就懵了。正确做法每做完一道题花5分钟写一下解题思路、时间复杂度、空间复杂度以及这道题属于哪一类滑动窗口、双指针、背包问题等。误区二死磕难题刚学会数组就去挑战“接雨水”“正则匹配”被打击得体无完肤。其实面试中70%是中等题20%是简单题只有10%是难题。先打好基础再说。误区三只看题解不自己写看一遍题解觉得“懂了”合上手机就写不出来。编程是手艺活必须自己动手敲哪怕照着题解敲一遍也行但一定要自己敲出来。2. 科学的刷题路线按知识点分类阶段时间内容目标题量基础期1-2个月数组、链表、栈、队列、哈希表30-50道提高期2-3个月树、递归、回溯、二分查找、排序40-60道进阶期2个月动态规划、图、并查集、高级数据结构30-40道冲刺期1个月模拟面试、高频题、错题重刷按需3. 大厂面试的高频知识点权重知识点出现频率典型题目数组/字符串⭐⭐⭐⭐⭐两数之和、盛最多水的容器哈希表⭐⭐⭐⭐⭐字母异位词分组、LRU链表⭐⭐⭐⭐反转链表、环形链表动态规划⭐⭐⭐⭐爬楼梯、最大子数组和二叉树⭐⭐⭐⭐二叉树的中序遍历、层序遍历双指针/滑动窗口⭐⭐⭐⭐无重复最长子串栈/队列⭐⭐⭐有效括号、最小栈回溯⭐⭐⭐全排列、组合总和排序/二分⭐⭐⭐快速排序、搜索旋转有序数组八、学习资源推荐——少走弯路一步到位1. 在线刷题平台LeetCode全球最权威的算法面试题库建议开会员看“企业题库”。牛客网国内校招面试题很全还有在线笔试模拟。Codeforces / AtCoder适合竞赛选手难度偏高。2. 经典书籍《算法第4版》SedgewickJava实现图非常多适合系统学习。《剑指Offer》何海涛面试经典题集很多大厂真题来源。《程序员面试金典》Gayle Laakmann系统面试指南不光算法还有系统设计。3. 视频课程B站“尚硅谷”数据结构Java版讲得很细免费。慕课网《算法与数据结构》波波老师由浅入深口碑很好。YouTube“NeetCode”英文题解思路清晰适合刷LeetCode。4. 图文/可视化网站Visualgo可视化数据结构和算法的执行过程一目了然。算法可视化 - 旧金山大学可以自己拖拽看排序、树的遍历过程。九、总结——从今天开始你离大厂只差一个“坚持”写到这里你可能已经发现数据结构与算法并没有想象中那么可怕。它们不过是我们描述世界、解决问题的工具而已。数组就像一个个整齐排列的抽屉方便你“随便抽一个”链表就像一条珍珠项链你想在哪里加一颗珠子都很方便栈就像一叠盘子最后洗的先用队列就像排队打饭先来先服务哈希表就像一把万能钥匙一拧就开树就像公司组织架构上级管下级图就像朋友圈你关注的人可能也关注着你。而算法二分、分治、动态规划、贪心、回溯就像是解决问题的五种“武功心法”。最后的最后给你三个最真诚的建议不要等“准备好了”再开始。你永远没有完全准备好的那一天。从今天开始打开LeetCode从“两数之和”做起。哪怕每天只做一道题坚持三个月你会发现自己的进步。不要怕犯错更不要怕看题解。看题解不是作弊是学习。但看懂了之后一定要关上题解自己重新写一遍直到能流畅写出为止。面试不是考你记住多少道题的答案而是考你遇到新问题时能不能用已有的知识去分析、拆解、解决。所以理解每一个数据结构为什么存在、每一个算法为什么适用比死记硬背重要一百倍。祝你早日拿到心仪的Offer。如果这篇文章对你有帮助请给个赞或者转发给同样在准备面试的朋友。我们一起卷得有价值。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑