news 2026/10/6 1:09:22

算法题总结274:面试前的高频题库与刷题攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题总结274:面试前的高频题库与刷题攻略

简介:面向算法面试与职场进阶的经典题目整理文档,适合正在准备大厂笔试、日常刷题巩固的开发者使用。资源以单个文档封装,共一个文件,大小约3.36MB,便于离线阅读与检索。目前已有177人学习浏览。文档参考主流刷题平台与经典面试书,系统整理高频考点,并按数组、字符串、链表、树、栈和队列、数学、图、设计、海量数据及C/C++基础等模块分类。各专题均围绕典型题目给出思路梳理,例如数组中重复的数字、旋转数组的最小数字、二维数组中的查找、最长公共子序列、正则表达式匹配等,既覆盖基础数据结构操作,也涉及海量数据处理与系统设计片段。读者可按需跳转至薄弱章节,在面试前集中回顾核心解法,快速建立知识框架,避免盲目刷题,提升临场解题与代码手写能力。

1. 算法题总结 274:我为什么推荐把这份题库当面试前的“悔过书”

算法题这东西,总有那么一批人,刷了三百道还是心里发虚;也有另一批人,拿着这份 274 题的中文答案解析,一周时间就把核心考点过了一遍,去面试时反而能清晰讲出思路。这份《算法题总结 274.pdf》我看下来,最大的特点不是“题多”,而是“题源干净”——题目来源集中在《剑指 offer》、LeetCode、LintCode、HihoCoder 和《王道程序员求职宝典》,正好覆盖国内大厂和互联网公司技术面最爱问的那些原题变体。它把题目按数组、字符串、链表、树、栈和队列、数学、图、设计、海量数据、C/C++ 基础十个专题分类,每个专题都有独立目录,基本可以当一本“算法面试速查手册”用。适合谁?两类人:一类是马上要面试、需要短时间内过一遍高频题型的求职者;另一类是刷题时老是卡在“知道思路但写不出来的”阶段,需要一份带参考答案的源码包来做对比复盘的人。有了这份题库,你缺的不是题,而是“先做、再对、再总结”的闭环。

2. 数据结构与算法面试的底层逻辑:为什么刷题前先要懂考察点

2.1 面试官到底在考察什么:从“暴力枚举”到“最优解”的思维升级

很多人在刷题时有一个误区:以为面试官要看的是“你写出了正确答案”。实际上,绝大部分面试官更在意的是你“怎么想到的”,以及“从暴力解到最优解的推导过程”。一份好的题库,价值恰恰在于覆盖这类推导路径。比如“数组中重复的数字”,最基础的解法是用哈希表,时间 O(n),空间 O(n);但面试官往往会追问:如果要求 O(1) 空间,怎么处理?如果你看过这道题,你就能答出“把值和下标对应,不断交换”的套路,这就是典型的“基于数组本身作为哈希表”的优化思路,也是国内面试最常考的考点之一。

我在面试别人时,最常做的事是:先让候选人说思路,再问复杂度,最后让他写代码。如果你刷题时只做了最后一步,那你相当于把考试中最容易得分的过程分扔掉了。用这份题库练习时,我建议你把每道题的“题目类型”先过一遍,比如这题是考“查找、排序、动态规划、贪心、回溯,还是位运算”,再动手做。只有能判断每道题属于哪个考察维度,你在面试中遇到陌生题时,才不至于无从下手。

2.2 数据结构的选型:这道题用数组还是链表、栈还是队列

从这份题库的目录可以看出,数组和链表是绝对的重头戏,占了将近 50 道题。数组类题目考察的是:指针和下标操作、二分查找的边界条件、连续子数组的累积和与累积积、排列组合的去重、以及数组原地操作的能力。链表题则是另一个方向:指针操作容易出现 null 指针引用、循环链表的判断、两个链表的公共节点、反转类问题,这些都是高频考点。

我的做法是:每做完一道题,在题目旁边标记“这道题如果换一种数据结构会不会更简单”。比如“用两个栈实现队列”——你如果用数组硬模拟当然也能做,但如果在面试中提到栈的 push/pop 天然是倒序的,就能自然引出“两个栈实现先进先出”的解法,这种“结构决定解法”的思考习惯,面试官更买账。同样,像“包含 min 函数的栈”,核心是用一个辅助栈记录当前栈内的最小值,而不是每次调用 min 时去遍历一遍主栈——这种“空间换时间”的思路,本身就是很多题目背后的通用解法。

2.3 经典算法模式的归纳:二分法、双指针、动态规划、剪枝

这份题库的第 1 题到第 30 题之间,几乎覆盖了最常见的算法模式。旋转数组的最小数字、旋转数组中查找数字、有序数组中查找数字的范围、数组中任一峰值的下标都属于二分法家族。它们的核心共同点是:在“部分有序”的数组中,我们总是能找到某种“中点判断”规则,把搜索区间缩小一半。每次刷这类题,我都建议用表格记录一下“mid 拿 left 还是 right、要不要加 1、循环条件写 left < right 还是 left <= right”,复盘时就一目了然。

双指针则是数组类题的另一大模式,比如“和为 s 的两个数字”、“求连续正数序列”、“盛最多水的容器”。这类题的共同套路是:用两个指针从两端向中间收缩,或一快一慢从同端前进。它比哈希表更节省空间,时间复杂度又往往能达到 O(n),是面试中最好用、也最好讲的一类解法。

动态规划在这个题库里的身影也不少:正则表达式匹配、通配符匹配、最长公共子序列、最长公共子串、最长回文子串、单词拆分、多个字符串的最长公共前缀、数字字符串解码。这些都是面试中“动态规划族”的入门题,特点是转移方程能背下来,但写对初始化常常要靠经验。用这份题库练 DP 时,我的习惯是:先把状态定义写清楚,再把 base case 给出来,最后再写转移方程。顺序反了,很容易在“边界”上翻车。

2.4 常见算法题的复杂度对比

模式典型题目时间复杂度空间复杂度适用条件
暴力枚举数组中重复的数字O(n²)O(1)数据量小,面试兜底方案
哈希表两数之和O(n)O(n)不要求原地,面试优先方案
双指针盛最多水的容器O(n)O(1)数组有序或有“两端逼近”特征
二分查找旋转数组的最小数字O(log n)O(1)数组部分有序,能判断中点方向
动态规划最长公共子序列O(mn)O(mn)有两段输入,满足最优子结构
位运算只出现 1 次的数字O(n)O(1)重复成对出现,想找单独一个

提示:上面的复杂度对比,是我自己在面试前复习时经常对着看的一张表。刷题时不要只追求 AC,还要能把“最坏情况复杂度”和“空间是否能优化”讲出来。

3. 把题库变成你的刷题计划:按专题攻克的实操步骤

3.1 第一步:用两周时间建立“高频题优先级清单”

拿到这份 PDF,第一件事不是从头到尾看,而是去“分析目录”。274 题看起来多,但如果你按专题再看一遍,就会发现:数组类 30 道、链表类 16 道、字符串类 14 道、树类 21 道、栈和队列类 8 道、数学类约 20 道、图类 5 道、设计类 0 道(题目较少)、海量数据类 8 道、C/C++ 基础约 4 道。真正面试中出现频率最高的是数组、链表、树,其次是字符串、数学、栈队列。

我的两周刷题计划大致是:第一周每天都只啃一个专题,早上一小时过思路,晚上一小时写代码;第二周开始混合刷,并且对第一周的薄弱专题做二次回刷。这样安排的好处是,你可以在一个专题里看到“同一个套路被不同题目反复使用”,比如“双指针”出现多次,刷完数组再刷链表,你就能总结出“凡是连续区间、相等元素、归并类问题,先想双指针”的直觉。

# 我自己用于刷题规划的一段简单脚本,用来统计 PDF 中每个专题的题目数量 # 粗略提取每行中“数字-题目名”模式,便于安排刷题顺序 import re content = """数组中重复的数字 旋转数组的最小数字 旋转数组中查找数字 有序数组中查找数字的范围 缺失的数字 数组中数值和下标相等的元素 查找数组中任一峰值的下标 数组中只出现 1 次的 2 个数 数组中唯一只出现 1 次的数字 数据流的中位数 和为 s 的两个数字 和为 s 的连续正数序列 数组中出现次数超过一半的数字 数组中最小的 k 个数 连续子数组的最大和 连续子数组的最大积 正则表达式匹配 通配符匹配 两个字符串的最长公共子序列 两个字符串的最长公共子串 反转链表 复杂链表的复制 合并两个有序链表 重建二叉树 中序遍历的下一个节点 二叉树的最大路径和 用两个栈实现队列 斐波那契数列 丑数 二进制中 1 的个数""" # 按空格拆词,统计常见专题词出现的频率 wordlist = content.split() freq = {} for w in wordlist: if w in ("数组", "链表", "字符串", "树", "栈", "队列", "数学", "图", "递归"): freq[w] = freq.get(w, 0) + 1 for topic, n in sorted(freq.items(), key=lambda x: -x[1]): print(f"{topic}: {n}")

这段脚本的逻辑很简单:把目录里的关键词按空格切开,统计“数组、链表、字符串、树、栈、队列”等专题词出现了多少次,输出一个粗略的专题题量排序。你不需要跑这个脚本,只要照着这个思路去自己翻 PDF 的目录,也能得出“数组 30 个、链表 16 个、树 21 个”这样的结论。关键是:刷题前需要有优先级,而不是从头刷到尾。

3.2 第二步:针对每个专题执行“读题-写思路-对答案”的闭环

我复习时的执行办法是:

  • 每道题先自己读题,要求自己在 5 分钟内想到思路,至少写出时间复杂度和空间复杂度。
  • 然后不看答案,尝试直接在白纸上写代码,先不管能不能跑通。
  • 写完再看 PDF 里的参考答案,对比差异:是“结构上的差异”还是“细节处理上的差异”。
  • 最后把这道题的“坑点”记在题目旁边,比如“空链表”、“负数”、“整数溢出”、“中点和 left/right 的更新”。

这样做看似费时,但题目质量决定了它的价值——这些题基本都是面试原题或原题变体,你练的不是“AC 能力”,而是“面试表达能力”。比如“二进制中 1 的个数”这道题,如果只写一个常规的循环右移,面试官大概率会问“有没有 O(1) 的算法”;如果你答出n & (n - 1)不断消去最右边的 1,面试官会觉得你是真正理解位运算的。

3.3 第三步:用题目标签反向建立“解题套路库”

刷完一两周后,你会发现自己记住了解法,却没有记住题目的视觉特征。这时候建议做一件事:把这份 PDF 中出现的题目,按“解法套路”重新归类。比如:

  • 凡是“有序数组中查找 xx”的,必是二分变形题。
  • 凡是“从一个数组的所有子集中找 xxx”的,大概率是回溯 + 剪枝。
  • 凡是“字符串匹配、公共子序列、编辑距离”的,基本是二维 DP。
  • 凡是“连续子数组”的,先想过一遍前缀和,再看是简单累计还是 DP。

我在刷这份题库时,建了一个小表,按套路分类。比如“数组”里“连续子数组的最大和”是一维 DP 的基础模型;“连续子数组的最大积”则需要记录最大值和最小值,因为负数相乘会反转大小关系。这些“分类学”不是题目本身给的,而是刷完题后自己总结的,但它才是面试现场回答“为什么这么解”的真正素材。

// 以“连续子数组的最大积”为例,核心是维护 max_cur 和 min_cur 两个变量 #include <vector> #include <algorithm> using namespace std; int maxProduct(vector<int>& nums) { if (nums.empty()) return 0; int max_cur = nums[0], min_cur = nums[0], ans = nums[0]; for (int i = 1; i < nums.size(); ++i) { int tmp_max = max_cur, tmp_min = min_cur; // 当前元素若为负数,乘以原来最大值会变成最小值,乘以原来最小值会变成最大值 max_cur = max({nums[i], tmp_max * nums[i], tmp_min * nums[i]}); min_cur = min({nums[i], tmp_max * nums[i], tmp_min * nums[i]}); ans = max(ans, max_cur); } return ans; }

这个解法的核心在于:数组里出现负数时,简单的“记录最大积”失效,必须同时记录最小积。由于max_cur和min_cur在更新时会相互依赖,所以用tmp_max和tmp_min保存更新前的值。代码写法上要留意std::max({...})是 C++11 的 initializer_list 写法,如果你在面试中手写,也可以用两两比较的方式,但思路必须说明“为什么需要双记录”——这是面试官考察的点。

3.4 第四步:做一份自己的“高频错题清单”

刷题过程中,那些第一遍没写对的题,才是你真正需要二刷的。我习惯用这样的记录方法:

  • 题号:把 PDF 里的题号抄下来,方便查找。
  • 题型:二分/DP/回溯/位运算/链表指针。
  • 错误类型:边界没考虑 / 递归出口写错 / 复杂度不达标 / 思路完全卡住。
  • 一句话解法:用自己能理解的话写出解法,不是抄答案。

比如“旋转数组的最小数字”,第一遍做错的人非常多,原因是把nums[mid] > nums[right]的条件写成 ≥,结果在重复元素出现时崩了。如果你在错题清单里写上“mid 与 right 比较,若等于 right,则 right-- 去重”,那你下次遇到类似题,就会比只看答案的人稳得多。

3.5 真题实战演示:从读题到 AC 的完整推演

举个括号匹配的例子。题目“有效的括号”在题库第 144 题,看起来是链表之外的独立小题,但实际非常能考察栈的使用。核心思路是:左括号入栈,右括号出栈并校验匹配,最后检查栈是否为空。

def is_valid(s: str) -> bool: stack = [] pairs = {')': '(', ']': '[', '}': '{'} for ch in s: if ch in pairs: if not stack or stack[-1] != pairs[ch]: return False stack.pop() else: stack.append(ch) return not stack

这段代码的关键是用了字典来映射右括号到左括号,而不是三个 if 判断,这样扩展性强,也更容易写对。参数说明很简单:s是输入字符串,遍历时如果是右括号,就看栈顶是否匹配;如果是左括号,就直接入栈。这个题还有两个变体:一是“括号嵌套并包含加减乘除”的计算器——LeetCode 227/772,那才是中高级面试题;二是“括号的分数”或“移除无效括号”,但思路都建立在栈这个基本功上。

4. 链表、树与递归:大部分人的分水岭都在这里

4.1 链表题的指针陷阱:null 判断、dummy 节点、反转

链表题是新手最容易“看答案觉得简单、自己写就崩”的专题。原因只有一个:指针操作涉及前置节点、当前节点、后置节点,任何一个环节忘了保留引用,链表就断了。这份题库里“反转链表”、“链表中间节点”、“链表中环的入口节点”、“删除链表中的节点”、“合并两个有序链表”都是最经典的题,它们的共性解法是“三指针法”。

以反转链表为例,解法是prev = null, cur = head,然后循环中先用next = cur->next保存后置节点,再把cur->next = prev,最后推进prev和cur。看似简单,但面试中最常犯的错误是:反转完,头节点没有指向新的头部;或者在循环结束后,返回了cur而不是prev。刷链表题时,最忌讳只看代码,应该自己画一遍链表图,每行代码对应一次指针变化。

// 反转链表的非递归实现 ListNode* reverseList(ListNode* head) { ListNode* prev = nullptr; ListNode* cur = head; while (cur != nullptr) { ListNode* next = cur->next; // 先保存下一个节点,防止断链 cur->next = prev; // 当前节点指向前驱 prev = cur; // prev 前移 cur = next; // cur 前移 } return prev; // 循环结束时 prev 指向新链表头 }

这里有个非常容易忽视的点:最后的return prev而不是return cur。因为循环结束时cur已经变成nullptr,而prev才是原来的尾节点,也就是反转后的头节点。很多新手写第一遍时都会在这里翻车,所以我会强调一遍:链表题写完之后,先手动跑一个单节点链表和三节点链表的用例,确认返回值不是空指针。

4.2 树的递归套路:遍历、子树、路径和祖先问题

二叉树问题在面试中的占比极高,它的核心解法其实是递归。树的面试题无非几种模型:

  • 遍历类:先序、中序、后序、按层,考察栈和队列的使用。
  • 路径类:二叉树中和为某一值的路径、二叉树的最大路径和,后两者考的是“从叶节点向上累加”。
  • 子树类:镜像、对称、子结构,这类题通常是“对每个节点递归判断”。
  • 构建类:重建二叉树、二叉树转双向链表,这类题要用“分治 + 中序/前序的边界计算”。

拿“重建二叉树”来说,题目给前序和中序遍历序列,要求重建二叉树。核心是找到前序第一个节点就是根节点,然后在中序里定位根节点的位置,用来切分左子树和右子树。这个题的代码量不大,但边界条件很多——中序区间为空时怎么办?前序区间的起始下标怎么算?这些细节,第一次手写几乎都会错。

// 根据前序和中序遍历重建二叉树 TreeNode* build(vector<int>& pre, int preL, int preR, vector<int>& vin, int vinL, int vinR) { if (preL > preR || vinL > vinR) return nullptr; TreeNode* root = new TreeNode(pre[preL]); // 在中序序列中找根节点下标 int idx = vinL; while (vin[idx] != pre[preL]) ++idx; int leftLen = idx - vinL; root->left = build(pre, preL + 1, preL + leftLen, vin, vinL, idx - 1); root->right = build(pre, preL + leftLen + 1, preR, vin, idx + 1, vinR); return root; }

这里的参数preL、preR、vinL、vinR是闭区间边界。每次递归时,前序的左子树区间长度等于中序左子树的长度leftLen,这个长度是从idx - vinL算出来的。如果中序里找不到根节点,说明输入序列不合法,但面试题默认输入是合法的;如果前序区间和中序区间长度不一致,也要直接返回空。做这类题,先画一个 5 个节点的二叉树,手动推一遍每组下标,比对着代码看十遍都有效。

4.3 递归转迭代:什么时候改用栈或队列更稳

很多树题用递归非常简洁,但面试也喜欢问“能不能不用递归”。最典型的是中序遍历的非递归实现:用栈模拟系统栈,从根节点开始,先把所有左孩子入栈,然后弹出、访问、再转向右孩子。

// 非递归中序遍历 vector<int> inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> st; TreeNode* cur = root; while (cur != nullptr || !st.empty()) { if (cur != nullptr) { st.push(cur); cur = cur->left; // 一直往左走到底 } else { cur = st.top(); st.pop(); res.push_back(cur->val); cur = cur->right; // 左子树与根都处理完,转向右子树 } } return res; }

这个写法的好处是,空间复杂度是 O(h),h 是树高,而不是递归那样 O(n) 的调用栈。面试中如果题目要求“能否用迭代”,你给出这个版本,并且说清楚为什么比递归更省空间,会是非常加分的点。树的按层遍历则是另一回事,它需要用队列做 BFS;如果题目要求“之字形打印”,只要加一个层序奇偶判断就行。这份题库把这三题(按层不分行、按层分行、之字形)分别列出,说明出题人很清楚“层层递进”的考察逻辑。

5. 算法题避坑指南:这五个坑,几乎每个刷题的人都踩过

5.1 二分查找的死循环:不是所有 mid 都要mid = left + (right - left) / 2

现象:写旋转数组最小数字这类题时,死循环或返回错误下标,尤其在数组长度为 2、元素重复时特别容易重现。 原因:当mid的更新策略与区间边界不一致时,左边界永远不会前进。比如left = mid时,如果mid又等于 left,则left永远不变。 解决:统一使用mid = left + (right - left) / 2(下取整),并确保每次循环区间至少缩小一个元素——即left或right的移动必须发生在mid被排除之后。用while (left < right)配合mid < target时left = mid + 1、否则right = mid这套模板能减少精神内耗。

5.2 链表题的“断链”问题:反转和删除时没保存后继节点

现象:把cur->next指向前一个节点之后,原链表的后半段“丢了”,或者遍历时指针越界。 原因:修改cur->next前,没有用临时变量保存cur->next的原始值。 解决:写链表题时养成“动 next 之前先备份”的习惯。如果要删除某个节点,也要考虑“尾部节点怎么处理”和“头节点怎么处理”两个边界。我一般会在代码开头写注释// next = cur->next 必须放在修改 next 之前,提醒自己。

5.3 位运算骚操作的不适配场景:n & (n - 1)不是万能的

现象:做“二进制中 1 的个数”时,直接用n & (n - 1)统计,结果在输入为负数时出错,或者循环次数过多。 原因:n & (n - 1)对于负数,比如-8,会得到-16,并不是简单消掉最右边的 1;而且如果只向右移位,负数的符号位会导致右移永远补 1,形成死循环。 解决:处理负数时,要么先强转成无符号整数unsigned int,要么右移时用逻辑右移(Java 的>>>),C++ 则转unsigned再处理。这道题是很多大厂的高频题,刷题时如果只背结论,面试时被追问负数场景就会非常尴尬。

5.4 动态规划的状态定义搞反:先写转移方程,后回填 base case

现象:很多人在做“最长公共子序列”时,dp[i][j] 定义成“以 i 结尾的最长公共子序列”,结果在字符不相等时的转移方程完全写不出来。 原因:状态定义选择错误。正确的是 dp[i][j] 表示“第一个字符串前 i 个字符与第二个字符串前 j 个字符的最长公共子序列长度”,而不是“以 i 结尾”。 解决:先定义状态、再写转移方程、再填 base case。char 相等时dp[i][j] = dp[i-1][j-1] + 1,不相等时dp[i][j] = max(dp[i-1][j], dp[i][j-1])。如果你发现某个状态定义导致转移方程出现“既要又要”,大概率是定义错了。

5.5 海量数据题的“伪最优”:位图与布隆过滤器分不清边界

现象:做“某个数是否在 40 亿个数中”、“2.5 亿整数中只出现一次的整数”这类题时,第一反应是排序或哈希,但面试官追问内存限制时答不上来。 原因:位图和布隆过滤器是海量数据题的常见解法,但它们的区别是:位图精确但范围固定,布隆过滤器是“一定概率误判”(适合判断“肯定不在”、无法判断“一定在”)。 解决:看到“40 亿个数查是否存在”时,用 2^32 位(512 MB)的位图;看到“多个大文件去重”且允许少量误判时,用布隆过滤器;看到“统计 URL 重复次数”时,就要考虑哈希分桶而不是位图。刷这类题时,要自己多问一个“空间限制是多少、是否允许误差”,答案往往就在这两个条件里。

# 位图实现示例:适合用在“40亿个数中查某个数是否存在” class Bitmap: def __init__(self, size: int): self.size = size self.bits = [0] * ((size + 31) // 32) def set(self, num: int): idx, offset = num // 32, num % 32 self.bits[idx] |= (1 << offset) def test(self, num: int) -> bool: idx, offset = num // 32, num % 32 return (self.bits[idx] >> offset) & 1 # 假设有 40 亿个数,用 int 列表模拟位图 bm = Bitmap(2**32) arr = [123456, 888888, 123456789] for v in arr: bm.set(v) print(bm.test(888888)) # True print(bm.test(999999)) # False

这个位图的实现用每个比特位表示一个数的存在性,内存开销是 n/8 字节。当整数范围是 0~2^32 时,2^32/8 字节约 512MB,对现代服务器来说并不是不能接受。它的最大优点是查找时间是 O(1),且不需要额外的哈希表结构,但缺点是只能判断存在与否,不能统计频次。遇到“只出现一次”的变体,就要用“两个位图分别记录出现零次、一次、多次”的扩展方法。

6. 把 274 题变成你自己的算法笔记:模板记忆法与三刷验证法

6.1 用“模板记忆法”替代题海战术

刷题到最后,拼的不是“见过多少题”,而是“能快速把新题归入哪一类”。我建议在把这份题库刷完之后,做一个动作:把每个专题里的题目压缩成“一句话模板”。

二叉树:递归处理左右子树,返回值和参数决定能否剪枝。 链表:三指针遍历,删除类问题加 dummy 节点。 字符串:先判断是子串还是子序列,再用双指针或 DP。 数学:先想位运算、幂运算,再想数学推导。 海量数据:先问内存限制,再决定位图、分桶、布隆过滤器。

比如你见到“合并 k 个有序链表”,第一反应应该是“每次取 k 个头节点最小的节点,用一个大小为 k 的小顶堆维护”,而不是“从头开始逐个比较”。这份 PDF 的目录里恰好覆盖了合并两个有序链表和合并 k 个有序链表,前者是递归或双指针,后者是小顶堆。如果刷完两道题后你能得出“k 路归并这个套路”,那才叫把题刷透了。模板记忆法的核心是:不是为了背诵模板,而是为了在看到题目特征时,第一时间想到“这是哪一类”,这比临时推导节省大量时间,也能提升思路的完整度。

6.2 三刷验证法:一刷题型、二刷代码、三刷思考

我自己在实际准备面试时,会把一份资料刷三遍,每遍目的都不同。第一遍只做“题型归类”,看每道题的标题,能在 10 秒内说出“这道题要考察什么”,做到这一步你会对面试题有整体把握。第二遍是“代码实现关”,每道题只写一次,写完过用例,并把卡住的地方记录下来。第三遍在面试前一两天做,只看自己的笔记:错题清单 + 模板库 + 复杂度表格,快速在心里默述每道题的解法,不再重新写代码。

这样的三刷安排,能够克服“看着答案觉得很简单、自己写还是不会”的困境。尤其是第二遍,写不出来并不可耻,真正宝贵的是把自己卡住的那个点记下来——面试官最喜欢追问的正好就是这些“卡点”。职场面试不是考试,不求你会做多少题,而求你能把已经掌握的题目清晰地讲出来。

6.3 面试现场的时间分配技巧

面试时遇到算法题,我建议先用 1~2 分钟确认题意,用“输入是否可能为空、数字是否可能为负、重复元素是否考虑”这三个问题堵住题目的边界。再用 2~3 分钟说思路和复杂度,最后才动笔写代码。如果写代码过程中卡住了,不要沉默,要和面试官交流“我现在卡在边界处理上”,这不会减分,反而体现沟通能力。

在刷这份题库时,我最大的教训是:不要做无脑“AC 机器”。二刷时遇到做过的题,应该先默写思路,再写代码。通读答案的人往往是“看了答案——写一遍——过了——忘了”,过两周再来,还是不会。真正有效的是自己做不出来之后再看答案,然后在错题清单里写下“我卡在哪一步”,过一周再做一遍同样题型。从那以后,我每次面试前都会强制自己走一遍“一看目录归题型,二看错题清单,三默述复杂度”的流程,每次都至少能稳定发挥出自己刷过题的八成水平。希望这套方法,也能帮你在准备算法面试时少走弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 1:07:40

如何用好CCNA中文版试题分析PDF:考点拆解与实验复现指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:06:41

基于DeepSeek语义理解的电子病历挖掘与DRG控费实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:05:51

VCC、VDD、VSS、VEE、GND电路电源标识详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:05:49

FPGA实现MIPI CSI-2摄像头图像采集与调试实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:05:25

片上眼图实现原理:从EOM到2-D Eye Scan的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:05:24

TMC4671:单芯片FOC运动控制SoC原理与实战调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华