
标题是“Android-Flutter面经二--算法”。看到这个题目我估计不少人和我一样第一反应是移动端开发也要卷算法了尤其是 Flutter 出来之后很多人转念一想Dart 写业务都够忙了还刷题但现实是不管你是投 Android 岗位还是 Flutter 岗位只要稍微好一点的公司算法面试这一关就绕不开。这篇面经我尽量把我在准备过程中踩过的坑、总结出来的重点以及那些“看着会但其实很容易翻车”的考点都摊开来说清楚。这一篇是面经系列的第二篇核心只聊算法。我的出发点很简单既然要花时间刷题就刷在刀刃上。移动端算法面试到底考什么、不考什么为什么是这些东西有价值以及你在用 Kotlin 或 Dart 手写算法时有哪些细节需要注意——这些才是我真正想聊的。1. 移动端算法面试的“真实画像”不是竞赛是工程思维1.1 面试官到底想从算法题里看到什么我最早准备算法面试的时候犯过一个典型的错误以为面试官想考我多难的算法于是花大量时间去看竞赛题、冷门数据结构甚至去研究粒子群算法原理这种偏研究向的内容。后来面了几家公司又和做面试官的朋友聊过几次才发现移动端岗位的算法考察和算法竞赛完全是两码事。面试官问算法核心想验证三件事第一你的逻辑思维是不是清晰能不能把一个模糊的问题拆解成明确的步骤第二你对基础数据结构和基础算法的掌握是否扎实而不是背过多少偏门模板第三你写出来的代码是不是具备可读性和健壮性这在工程里比“最优解”更重要。换句话说面试官不是在找 ACM 选手而是在找“能一起干活的人”。一道题你写出 O(n^2) 的解法但是逻辑清晰、边界条件处理到位一定会比憋了半天写不出 O(n) 解法、最后还一堆 bug 强得多。我见过太多候选人包括当初的我自己一上来就想“秀操作”结果操作没秀成连最基本的二分边界都写错。1.2 Android 和 Flutter 岗位的算法侧重点差异这里有一个比较容易被忽视的点就是 Android 岗位和 Flutter 岗位算法考察虽然都是“基础算法为主”但微妙的侧重点会有差异。Android 岗位更倾向于考和内存、性能、系统机制相关的题。比如数组和链表的区别会结合“ArrayList 和 LinkedList 在频繁插入删除场景下怎么选”来问HashMap 的底层原理会直接追问到扩容机制、红黑树化条件还会出现一些和“缓存淘汰”相关的场景题比如让你实现一个 LRU。而 Flutter 岗位因为它的 UI 渲染机制和响应式编程模型面试官会比较喜欢考树的遍历Widget 树、Element 树你懂的、状态管理里的数据流有时候还会从“Stream 怎么做防抖节流”引出“怎么用队列、定时器实现限流”这种题。Dart 的单线程事件循环模型也决定了“任务调度”“微任务和宏任务”这类题目在 Flutter 面评中出现的频率比纯 Android 岗位高。当然这只是一般规律不是绝对。但摸清这个侧重方向至少能让你的刷题范围更聚焦。1.3 关于“热搜算法”的冷静判断我刷热搜词的时候看到“粒子群算法原理”“规则引擎 Drools 的 Rete 算法实现原理”“KL ELBO 算法原理详解”这些词挂在前面说实话我的第一反应是搜索引擎的热搜词不等于面试的高频考点。我不否认有些做 AI 方向或者音视频算法的岗位会问粒子群、音频重采样算法这类东西但那是“某个具体方向的专业面试”不是通用的“算法面试”。你要投的是 Android/Flutter 开发岗把时间砸在这些偏研究向、偏特定领域的算法上性价比真的很低。通用算法面试的高频区间永远是数组、链表、字符串、树、哈希表、排序、二分、贪心、动态规划这几板斧。你把这些吃透了覆盖 80% 以上的面试题没任何问题。剩下 20% 里偶尔会冒出个位运算、并查集、KMP 之类的东西后面我会单独讲。2. 高频考点范围拆解哪些必须吃透哪些看着热其实不考2.1 必考核心区数据结构与基础算法我把移动端算法面试的考察内容列成了一张表按出现频率和重要程度分了三档。你可以对照着查漏补缺。层级考点典型题目/场景准备程度第一梯队数组、链表反转链表、合并有序链表、寻找中位数、双指针必须手写熟练所有变体烂熟于心第一梯队哈希表两数之和、LRU 缓存、字母异位词分组必须理解底层原理会用哈希优化第一梯队字符串最长无重复子串、字符串翻转、回文串判断双指针和滑动窗口是核心武器第一梯队排序快排、归并、堆排序的手写实现必须能默写并且知道时间/空间复杂度推导第一梯队二分查找有序数组查找、旋转数组中找目标、sqrt 实现边界条件必须烂熟需反复练习第一梯队树二叉树的前/中/后/层序遍历、最近公共祖先、路径总和递归和迭代两种写法都要会第二梯队贪心算法跳跃游戏、买卖股票、区间调度/合并和动态规划经常放一起考察第二梯队动态规划爬楼梯、背包问题、最长递增子序列必考大户但常考的是经典简单/中等题第二梯队栈与队列用栈实现队列、单调栈、括号匹配代码量不大但思路要非常清晰第二梯队滑动窗口/双指针最小覆盖子串、三数之和、盛最多水的容器中等题的高频出题方向第三梯队位运算只出现一次的数字、2 的幂偶尔出现但通常只是小题第三梯队并查集岛屿数量、朋友圈Flutter/Android 面试出现概率低第三梯队KMP字符串匹配、next 数组属于“加分项”不是人人必考基本不考粒子群、模拟退火、Rete、ELBO偏向特定研究方向除非你是算法岗/特别对口否则不用浪费时间我知道把 KMP 放进第三梯队可能会有人不同意毕竟它的名字在热搜词里很显眼。我的观点是KMP 在移动端面试中确实会考但更常出现在“面试官想深入考察你字符串处理能力”的场景或者作为压轴难题出现。你至少应该知道它的核心思想和 next 数组的求法但不一定要像快排一样做到条件反射。2.2 “刷题数量”和“刷题质量”的取舍很多人在准备算法面试时有一个执念刷满 300 题、500 题刷完 LeetCode 热门题。我的体感是对于移动端岗位刷题质量远比数量重要。什么叫质量就是你把一道中等的经典题吃透做到闭着眼能写出正确解法并且能说清楚“为什么是这样做”“还有没有更好的解法”“如果数据规模变化了会怎样”。一道题你用自己的思路写出来再对照最优解找差距这比囫囵吞枣刷十道题有效得多。我自己备考的时候有一个“二刷才有收获”的体会。第一遍做出来的题过两周再看很大概率写不出来。这不是记性差而是你当时并没有理解到足够深。第二遍做的时候你才会真正开始注意细节比如一棵树用递归很容易但用迭代怎么控制栈的顺序、快排的 pivot 怎么选最稳妥这些藏在“能跑通”背后的东西。2.3 不在同一条路上纠结太久还要提一个“止损”策略。当你发现一道题卡了超过 30 分钟还完全没有思路果断看题解。不要有负罪感。面试又不是闭卷考试你现在看题解是为了积累“解题套路”而不是证明自己的智商。看到题解以后合上答案自己重新写一遍。如果第二天还能独立写出来这题你才算真正会了。如果写不出来说明你只是“看懂了”和“会做”还差着一个复现的距离。这是我在准备过程中反复经历的也是进步最快的阶段。3. 高频算法原理解析与手写模板从原理到默写3.1 KMP 的 next 数组别再死记硬背了先聊 KMP因为热搜词里出现了“在 KMP 算法中对于模式串 pabacaba其 next 数组next[i] 定义为…”我就拿这个例子来拆。KMP 解决的核心问题是字符串匹配中主串指针不回溯的问题。朴素匹配算法在每次失配时主串指针都要回退到下一个位置重新开始最坏时间复杂度是 O(m*n)。KMP 的聪明之处在于它提前计算好模式串自身的前后缀匹配信息next 数组这样匹配失败时主串指针不用动模式串直接跳到下一个可能匹配的位置。next[i] 的定义是在模式串 P 中P[0...i]这个子串的“最长相等前后缀长度”。注意这个长度不能等于子串本身长度。我们拿abacaba来手算一遍i0子串是a。没有真前缀和真后缀next[0]0。i1子串是ab。前缀a后缀b不相等next[1]0。i2子串是aba。前缀a后缀a相等长度 2 的ab和ba不相等。所以最长相等前后缀长度是 1next[2]1。i3子串是abac。前缀a、ab、aba后缀c、ac、bac。没有相等的next[3]0。i4子串是abaca。前缀a、ab、aba、abac后缀a、ca、aca、baca。只有a和a相等next[4]1。i5子串是abacab。前缀a、ab、aba、abac、abaca后缀b、ab、cab、acab、bacab。最长相等的是ab长度 2所以 next[5]2。i6子串是整个abacaba。前缀a、ab、aba、abac、abaca、abacab后缀a、ba、aba、caba、acaba、bacaba。最长的相等前后缀是aba长度 3。所以 next[6]3。所以abacaba的 next 数组是[0, 0, 1, 0, 1, 2, 3]。写出代码模板fun buildNext(p: String): IntArray { val next IntArray(p.length) var j 0 for (i in 1 until p.length) { while (j 0 p[i] ! p[j]) { j next[j - 1] } if (p[i] p[j]) { j } next[i] j } return next }这个模板里的难点就是while (j 0 p[i] ! p[j]) j next[j-1]。你不需要背只需要理解j记录的是当前已匹配的前缀长度如果当前字符失配就回退到上一个最长的相等前后缀状态继续尝试。这就是 KMP 的“自我匹配”。写 KMP 时最容易翻车的点有两个一个是 next 数组的索引和主串/模式串索引的错位另一个是“最长相等前后缀”里忘了它不能等于子串本身。你拿abacaba这个例子多走几遍比背任何口诀都管用。3.2 排序快排和归并是移动端面试的“默写题”排序算法在移动端面试里的地位有点像一个演员的“基本功”。你说它是送分题吧但每年挂在手写快排上的候选人一抓一大把。我不能说大数据结构排序算法不重要但移动端面试真正让你“手写”的也就是快排、归并和堆排序。快排的核心是 partition。我推荐用“挖坑法”或者“左右指针法”来实现逻辑直观不容易错。这里给一个 Kotlin 的版本fun quickSort(nums: IntArray, left: Int, right: Int) { if (left right) return val pivot nums[left] var i left var j right while (i j) { while (i j nums[j] pivot) j-- nums[i] nums[j] while (i j nums[i] pivot) i nums[j] nums[i] } nums[i] pivot quickSort(nums, left, i - 1) quickSort(nums, i 1, right) }面试官追问快排的时候通常会问“最坏时间复杂度是多少”。答案要说清楚有序数组 每次取第一个元素当 pivot会导致分区极度不平衡退化成 O(n²)。所以要提随机化 pivot。这个细节很简单但加了它你在面试官眼里的分量会明显不一样。归并排序的模板重点在于递归拆分的“分治思想”和合并时的额外空间。堆排序在移动端面试里出现频率略低于快排和归并但“Top K 问题”会用堆来解决建议把堆调整的siftDown单独抽出来练习。3.3 贪心算法几个经典例子帮你建立“贪婪直觉”贪心算法的核心是“每一步都做出当前看起来最优的选择并且期望全局最优”。它的难点不是写代码而是判断一道题能不能用贪心、贪心策略是什么。面试中经常出现的贪心题目集中在“区间问题”和“跳跃类问题”上。区间调度给定一堆区间找最多能选出的互不重叠的区间数量。经典贪心策略是“按结束时间升序排序每次选结束最早的然后跳过所有和它重叠的区间”。你试着把多个 end 时间画到时间轴上会发现这个策略几乎是直觉性的。买卖股票的最佳时机 II可以任意多次交易但只能持有一股。贪心策略很简单只要今天的价格比昨天高就累加差价。很多人在这个问题上陷入“要不要等涨更多再卖”的纠结其实完全没必要——你把每一段上涨都吃到了收益就是最大的。跳跃游戏判断能不能跳到最后一个位置。贪心策略是维护一个maxReach遍历过程中不断更新“当前能跳到的最远位置”如果某个位置i maxReach说明卡住了返回 false。贪心题在面试中的另一种形态是“证明为什么贪心策略是对的”。面试官不一定会让你严格证明但你要能从反例角度解释比如“为什么区间调度里不能按长度升序排序”这样讲出来比单纯扔出一个结论要有说服力得多。3.4 动态规划从“爬楼梯”到“背包问题”的状态推导动态规划在移动端面试中几乎是“必考题”的存在但它通常不考那种一眼看穿的大难题而是考经典模型的小变体。备考思路就一条把经典模型的转移方程吃透然后背住代码骨架。爬楼梯/斐波那契是入门中的入门。dp[i] dp[i-1] dp[i-2]无非是加不加两个起始条件的区别。打家劫舍是“相邻不能选”的经典问题。dp[i] max(dp[i-1], dp[i-2] nums[i])。这题的面试价值在于它告诉你动态规划不一定是“选了第 i 个就一定怎么样”而是“在第 i 个位置做选择然后和之前的状态比较”。背包问题是所有动态规划类型里我个人觉得最值得投入时间研究的。0-1 背包的转移方程是dp[j] max(dp[j], dp[j - weight[i]] value[i])一维数组做 0-1 背包时内层循环必须从大到小遍历否则会重复选同一个物品。这个细节如果你不理解用“二维数组先写对再压缩到一维”的方式来准备会更安全。到了完全背包问题内层循环反过来从小到大——面试时如果能把这层差异讲透是很大的加分项。最后提醒一句动态规划题目刷题时先写出暴力递归版本再优化成带 memo 的递归版本最后改写成自底向上的 DP。这个过程能帮你深刻理解“状态定义”和“状态转移”比一上来就套模板要可靠。4. 用 Kotlin/Dart 手写算法语言特性带来的细节差异4.1 Kotlin 手写算法的常见陷阱与习惯如果你面试的是 Android 岗位面试官通常会允许你用 Kotlin 或者 Java。我建议优先用 Kotlin它更简洁。但 Kotlin 有几个和算法手写相关的陷阱你需要提前预防。第一个是数组创建。IntArray(n)创建的是基本类型数组初始值全部为 0推荐在算法题里使用。Array(n) { ... }创建的是装箱类型的数组写法啰嗦还容易性能踩坑。写二维数组时Array(n) { IntArray(m) }是正确的做法千万别写成Array(n) { IntArray(n) }——看起来没问题但每个子数组引用的是同一块内存。第二个是集合的默认实现。Kotlin 的listOf()返回的是只读列表不能用于需要修改的场景。算法题里经常要“模拟队列、栈”直接用ArrayList或ArrayDeque更顺手。第三个是和 Java 互操作时容易犯的错在算法题里往ArrayList里反复插入删除如果触发扩容和数组拷贝时间复杂度会比理论值高。但这个在面试阶段一般不会成为扣分点真正扣分的是逻辑错误。Kotlin 手写算法的一个小模板// 反转链表 fun reverseList(head: ListNode?): ListNode? { var prev: ListNode? null var cur head while (cur ! null) { val next cur.next cur.next prev prev cur cur next } return prev }这个模板我建议你多默写几遍。因为它短小、边界清晰而且能延伸出“翻转区间链表”“K 个一组翻转链表”等变体。4.2 Dart 手写算法Flutter 面试的独特体验说到 Flutter 面试一些候选人会疑惑面试官到底允不允许我用 Dart 写算法我的实际经验是大部分面试官是允许的毕竟你在面试的岗位就是 Flutter 岗位。但你自己得对 Dart 的语法了如指掌否则写起来会卡壳。Dart 和 Kotlin 在手写算法上的主要差异我整理了一张表场景KotlinDart创建数组IntArray(n)Listint.filled(n, 0)无序列表val list mutableListOfInt()final list int[];双端队列ArrayDequeInt()或LinkedList()ListQueueint()来自 collection 包Null 安全ListNode?用?.?:类型后加?用?.??元组/多返回值data class PairA, BRecordDart 3或自定义类Dart 的List本质上是动态数组和 Kotlin 的ArrayList是类似的东西。如果你的题需要“链表”这种结构Dart 没有内置 ListNode你需要自己定义一个class ListNode { int val; ListNode? next; ListNode(this.val, [this.next]); }没错就是这么简单。但很多人第一次在 Dart 里写链表题的时候会卡在“Dart 怎么没有 ListNode”这个问题上白白浪费面试时间。建议你提前在 DartPad 或本地环境里把常用数据结构的定义写一遍混个脸熟。还有一个需要注意的差异Dart 3 之前的版本不支持List模式匹配和Record如果你面试时用的环境是老版本 Flutter尽量不要写太新潮的语法。面试手写算法越朴素越稳。4.3 手写代码时的三个“专业习惯”除了语言本身的语法在面试现场手写代码时有几个习惯能让你看起来非常专业第一在写代码之前先明确“输入为空”“输入长度为 1”“全是重复元素”这几个边界。你可以在动手前用一句话说出来“我先处理一下空输入和单元素输入的情况。”面试官听到这句话对你的印象分会瞬间上提。第二变量名要有意义。不要用i, j, k满天飞至少用一个有语义的变量比如left、right、maxReach、windowStart。这不仅是给别人看的也是给你自己检查的时候减少思维负担。第三写完代码后主动跑一个简单用例沿着一两行核心逻辑走一遍。这一步能帮你发现大量“看起来没问题但实际会死循环/越界”的问题。面试官不会嫌你慢反而会觉得你做事有验证意识。5. 从读题到通过一道典型算法题的全过程拆解5.1 完整案例最长无重复字符子串这道题是面试中的“必刷之王”LeetCode 第 3 题。几乎每一轮 Android 或 Flutter 面试你都有概率碰到原题或变体。我就拿它完整拆一遍展示从读题到提交的标准流程。题目给定一个字符串 s请你找出其中不含重复字符的最长子串的长度。面试官说出题目后第一反应不是写代码而是先确认几个问题字符串只包含英文字母吗还是可以是任意 ASCII/Unicode 字符空字符串怎么办如果面试官说“可以是任意字符”那你的答案就要覆盖到 char 集。这个“沟通题意的能力”本身就是面试考察点。思路分析暴力解法是枚举每一个子串检查它有没有重复字符时间复杂度 O(n^3)显然不行。可以用哈希表 滑动窗口优化窗口内维护“当前无重复字符的子串”用两个指针 left 和 right 控制窗口范围right 向右扩展时如果遇到重复字符就把 left 跳到重复字符上一次出现位置的下一个。Kotlin 版本fun lengthOfLongestSubstring(s: String): Int { val lastIndex HashMapChar, Int() var left 0 var maxLen 0 for (right in s.indices) { val c s[right] if (lastIndex.containsKey(c)) { left maxOf(left, lastIndex[c]!! 1) } lastIndex[c] right maxLen maxOf(maxLen, right - left 1) } return maxLen }Dart 版本int lengthOfLongestSubstring(String s) { final lastIndex String, int{}; var left 0; var maxLen 0; for (var right 0; right s.length; right) { final c s[right]; if (lastIndex.containsKey(c)) { left lastIndex[c]! 1 left ? lastIndex[c]! 1 : left; } lastIndex[c] right; maxLen (right - left 1) maxLen ? right - left 1 : maxLen; } return maxLen; }注意 Dart 版本里我把left maxOf(left, ...)改成了三目运算符。因为dart:math的max函数对整数是可以用的但你在面试现场写三目其实更稳尤其在列表里需要嵌套运算时。复杂度分析每个字符最多被 left 和 right 各访问一次所以时间复杂度 O(n)空间复杂度 O(字符集大小)。这个分析要在代码写完后主动讲出来。面试官可能的追问方向如果要求返回最长无重复子串的字符串本身怎么改如果字符串特别长怎么优化内存如果允许你删掉一个字符再求最长怎么做这些追问不需要全部提前准备到完美但你可以顺着“滑动窗口 状态记录”的思路现场推导。5.2 面试官展示“思考过程”的小技巧我发现很多候选人写算法题时喜欢闷头写一笔一笔把答案写出来中间完全不出声。这其实很吃亏。面试官没法看到你的大脑活动你闷头写完的代码如果和他期望的思路不一致他只能猜你是怎么想的。更聪明的做法是“边想边说”。拿到题目后先用自己的话复述一遍题目再抛出最大路线的解法如果有更好的思路就补充说“我再优化一下”。比如这道最长无重复子串题你可以说“最直接的办法是枚举所有子串但那样复杂度太高。我想到用滑动窗口让窗口始终维护无重复字符这样每个字符只会被访问一次整体是 O(n)。”这么几句话面试官就清楚地知道你是真的理解了。还要注意在写代码的过程里卡壳了怎么办。不要硬撑着。可以停下来说“这块边界条件我需要再想一下”然后真的把它想清楚。面试官不会因为你短暂停顿扣分反而会因为你在关键边界上谨慎而加分。我见过不少候选人明明思路是对的就因为不好意思停下来思考最后写出一个“看起来完整但边界全错”的代码非常可惜。5.3 从“手写代码”到“和面试官讨论优化”算法题聊到最后面试官经常会问“还有没有更好的解法”。这时候不一定要真的给出更优解而是展示你“愿意优化”和“知道有哪些优化方向”的意识。你至少可以从三个方向思考时间换空间、空间换时间、利用题目特性。比如最长无重复子串这道题如果你发现字符集有限只有 26 个小写字母就可以用长度为 128/256 的数组代替 HashMap既省内存又提速。这类微优化不需要你提前背答案只要你“知道哈希表在这个场景下有更便宜的替代品”面试官就会觉得你底层基本功扎实。再比如如果面试官问“你这个代码有没有隐患”你主动指出“当 s 为空时循环不执行left 等初始值都正确maxLen 返回 0行为符合预期”这就是在展示你的工程思维。面试官不是想要一个会背题的人而是想要一个能写生产级代码的人。6. 备考路线与踩坑记录我的算法面试复盘6.1 我的备考时间线和刷题策略我是提前大概 8 周开始准备的目标是打基础 高频题 模拟面试三轮走完。前两周只看经典的“数据结构与算法”的章节内容不刷题。那时候我把 Linked List 在纸上画了一遍又一遍不是画图好看而是把指针怎么指、哪一步断了会导致什么后果完全在大脑里模拟出来。中间四周是“高频题专项”。我用的是 LeetCode 的 Hot 100 题单。我给自己定的规矩是每天 3 道题不求快但每道题都得“复现一遍”。意思是今天做完的题明天重新手写一遍。如果写不出来就意味着昨天那题根本没有真正掌握。这个过程很费时间但它的反馈非常真实就像你在面试现场临时想不起来的场景一样逼着你“能不能不看题解把逻辑补完”。最后两周进入“模拟面试模式”。我找了一个朋友每周抽三四天每天让我在约定时间内完成两道随机题他当面试官负责追问。模拟面试的收获比闷头刷题要大得多因为你会真切地感受到“有人看着你写代码”的压力也能暴露你语言表达上的问题。6.2 我踩过的三个“看起来很小但真的很致命”的坑第一个坑数组越界。你说这听起来像是新手才会犯的问题但越是在紧张状态下越容易在nums[i1]、j-1这类边界上翻车。我第二次刷题时才意识到一个数组越界抛出的异常在面试里基本等于“直接再见”。所以我现在每写一个循环都会习惯性地用“取到最后一个有效位置”的方式去检查边界而不会依赖“反正不会越界”的侥幸心理。第二个坑时间复杂度分析不准。我有一次面试写了两数之和一开始写出 O(n^2) 暴力解后来优化成了 O(n) 哈希表版本。但面试官紧接着问“如果数组非常大内存装不下这么多哈希怎么办”我愣了一下没接住。后来想想他要的是先衡量两种方案的优劣而不是无脑选哈希表。把复杂度分析从“能跑就行”升级到“适合当前场景”是我这次面试最大的收获。第三个坑把面试当成竞赛。我准备了一个多月自我感觉刷题量已经很充足结果到了现场反而因为“总想给一个惊艳的解法”导致第一道题绕了远路没有按最直接的方法答出来。面试官后来在评价里说“基础不错但喜欢绕弯子”。从那以后我给自己定了一条铁律面试中先写出正确、可读的解法再去考虑优化。这是顺序问题不能反过来。6.3 项目里聊算法的真实场景面试不只会考“手撕算法”还会从项目经历里引出算法问题。比如你做过音视频相关的 Flutter 项目就可能被问到“音频重采样怎么做”“FIFO 缓冲区怎么管理”。你做 Android 的图片加载优化就可能被问“图片列表滑动卡顿你怎么用算法思想解决”。这些问题本质上是考“算法思维在实际工程里的投射”而不是考你背过多少模板。同样的道理你用过 Retrofit可能被问到“OkHttp 的请求队列是怎么调度任务的”你做过 Flutter 的性能优化可能被问到“Widget 树重构时如何避免不必要的 rebuild这背后有没有类似记忆化的算法思想”。所以准备算法面试不能只盯着算法题本身你平时写的业务代码里那些用到的设计模式、性能优化点、缓存策略都能成为你和面试官讨论算法的引子。我个人觉得这比背下所有的题解重要得多。6.4 关于“算法岗 vs 开发岗”的最后提醒还有一个非常现实的问题你到底是投“算法岗”还是“开发岗”。这两个方向在算法面试上的差别非常大。算法岗会追问粒子群算法原理、推荐系统里的召回/排序、音频重采样算法、Rete 算法在多规则引擎里的匹配过程甚至会盯着 KL ELBO 的推导让你一步步推下去。这些都是正经的算法方向问题。但如果你是投 Android 或 Flutter 开发岗上面那些内容几乎可以全砍掉。你需要的不是“研究算法的能力”而是“用算法解决工程问题的能力”。开发岗的面评体系里基础数据结构的理解、边界条件的处理、代码的可读性和健壮性权重远大于“你会不会 SOTA 算法”。别搞反了。最后分享一个我个人的小体会面试算法题心态真的很重要。它更像一场“和面试官一起解一道题”的合作过程而不是“考生接受考官审判”的表演。你可以把面试官当成一个水平不错的同行边写边聊思路有不确定的地方就大方请教这种状态比紧绷着“我一定要写出完美答案”要自然得多也更不容易出错。这一篇面经写到这里核心想表达的东西已经聊透了先把范围收窄到高频考点再把经典模型吃透最后用符合你目标岗位的语言把模板练熟。剩下的就是多模拟、多复盘。如果我这篇经验能帮你在刷题路上少走几个弯那就值了。