majinxin 发布的文章

面试算法常见及经典题总结

适用对象:Android / 客户端 / 后端社招与校招,面试环节有手写代码或算法笔试的候选人。
核心目标:不靠题海死记,而是掌握 题型识别 → 解题模板 → 举一反三 的迁移能力。

一、面试算法考什么

1.1 常见考察形式

形式说明建议
白板 / 在线 IDE 手写1~2 道,45~60 分钟先讲思路再写,注意边界
笔试多题2~4 道,限时先易后难,暴力可拿部分分
追问复杂度几乎必问时间 + 空间,能否优化
代码质量变量命名、边界、可读性主流程清晰,边界集中处理

1.2 面试官真正想看什么

  1. 能不能把题翻译成算法模型(排序?双指针?DP?)
  2. 能不能分析时间空间复杂度
  3. 能不能处理边界(空、单元素、重复、溢出)
  4. 能不能在提示下优化(O(n²) → O(n))
  5. 代码是否可维护(不过度炫技)

1.3 备考策略

不要:按题号刷 500 道,做完就忘
要做:
  1. 掌握 12~15 个核心模式(本文第二节)
  2. 每个模式精做 3~5 道经典题
  3. 每道题总结「识别信号 + 模板 + 变体」
  4. 二刷时遮住答案,15 分钟内独立完成

二、题型识别总表(先认模式,再套模板)

识别信号首选模式典型关键词
两数 / 三数之和、去重配对哈希 + 双指针sum、pair、duplicate
连续子数组 / 子串最值滑动窗口连续、最长、最短、满足条件
有序数组查找 / 答案单调二分排序、第 k 大、最小化最大值
链表反转、环、合并链表双指针next、cycle、merge
括号匹配、单调性栈有效括号、每日温度
树的路径、遍历、最近公共祖先树 DFS/BFSroot、path、level
全排列、组合、子集回溯所有可能、不重复组合
最优子结构 + 重叠子问题动态规划最大/最小、方案数、能否达到
局部最优能推全局贪心区间、调度、跳跃
连通分量、冗余边并查集岛屿、朋友圈、最小生成树基础
TopK、流式第 K 大堆前 K 个、中位数、合并 K 路
只出现一次、异或性质位运算缺失数字、只出现一次

三、模式详解 + 经典题 + 举一反三


模式 1:哈希表(HashMap / HashSet)

核心思想

用 O(1) 查找 把「枚举配对」变成「一次遍历」。

经典题 1:两数之和(LeetCode 1)

题意:数组 nums、目标 target,找两数下标使和为 target。

思路

遍历 nums[i]:
  需要 complement = target - nums[i]
  若 map 里已有 complement → 返回答案
  否则 map[nums[i]] = i

复杂度:O(n) 时间,O(n) 空间。

代码骨架(Kotlin)

fun twoSum(nums: IntArray, target: Int): IntArray {
    val map = HashMap<Int, Int>()
    nums.forEachIndexed { i, v ->
        val need = target - v
        map[need]?.let { return intArrayOf(it, i) }
        map[v] = i
    }
    return intArrayOf()
}

举一反三

变体题变化点思路迁移
三数之和(15)固定一个数,剩下降为「两数之和」排序 + 双指针;去重跳过相同元素
四数之和(18)两重循环固定排序 + 双指针,注意剪枝
两数之和 II(167)数组已排序双指针左右夹逼,无需哈希
存在重复元素(217)判断是否有重复HashSet 边遍历边 contains
字母异位词分组(49)字符串分组用「排序后字符串」或「26 字母计数」作 key
最长连续序列(128)连续数字最长长度Set 存所有数;只从序列起点扩展
和为 K 的子数组(560)连续子数组前缀和 + HashMap 记「前缀和出现次数」

迁移口诀:

需要「有没有凑成 X」→ 先想哈希;需要「连续子数组和」→ 前缀和 + 哈希。

模式 2:双指针

核心思想

两个下标协同移动,把 O(n²) 枚举降为 O(n)。

子类型

类型移动方式场景
对撞指针left++ / right--有序数组求和、回文、盛水
快慢指针slow / fast链表环、去重、原地修改
同向双指针滑动窗口特例移动零、移除元素

经典题 2:盛最多水的容器(11)

思路

left = 0, right = n - 1
面积 = min(height[left], height[right]) * (right - left)
每次移动较短的那一侧(因为宽度一定变小,只有抬高短板才可能更大)

经典题 3:删除有序数组中的重复项(26)

思路:slow 指向已去重区间末尾,fast 扫描;不同则 slow++ 并赋值。

举一反三

变体题模式
验证回文串(125)对撞指针跳过非字母数字
三数之和(15)固定 i + 对撞指针
接雨水(42)对撞或单调栈(见模式 6)
链表环入口(142)快慢指针相遇后,一指针从头走
链表中倒数第 K 个(19)快指针先走 K 步
合并两个有序数组(88)从尾部双指针填入
移动零(283)slow 维护非零区,fast 扫描

迁移口诀:

有序 + 配对 → 对撞;链表 + 位置/环 → 快慢;原地修改数组 → slow/fast 同向。

模式 3:滑动窗口

核心思想

维护区间 [left, right],右扩左缩,使窗口满足(或恰好不满足)某条件。

模板

left = 0
for right in 0..n-1:
    将 nums[right] 纳入窗口(更新 count / sum)
    while 窗口不满足条件:
        将 nums[left] 移出窗口
        left++
    更新答案(最长 / 最短 / 计数)

经典题 4:无重复字符的最长子串(3)

思路:HashMap 记字符最后出现下标;若重复且在下标 ≥ left,则 left = last + 1。

经典题 5:最小覆盖子串(76)

思路:need / window 两个 Map;valid 计数;右扩直到满足,再左缩取最短。

举一反三

变体题窗口维护什么
长度最小的子数组(209)和 ≥ target,求最短 → 满足时左缩
找到字符串中所有字母异位词(438)固定窗口长度 + 计数比较
水果成篮(904)最多两种字符 → 种类数 > 2 则左缩
K 个不同整数的子数组(992)至多 K 种 → 转化为「atMost(K) - atMost(K-1)」
滑动窗口最大值(239)单调递减队列(见模式 6)

迁移口诀:

「连续子串 / 子数组」+ 最长/最短/满足条件 → 滑动窗口;固定长度窗口 → 右扩时同步左移。

模式 4:二分查找

核心思想

答案空间或数组具有 单调性,每次排除一半。

两种写法

类型场景要点
标准二分找 exact targetwhile (left <= right)
边界二分找第一个 ≥ x / 最后一个 < x缩区间,最后 check

经典题 6:搜索旋转排序数组(33)

思路:nums[mid] 与 nums[left] 比,判断哪半边有序,再判断 target 是否在有序半边。

经典题 7:在排序数组中查找元素的第一个和最后一个位置(34)

思路:两次二分,分别找左边界和右边界。

举一反三

变体题二分对象
搜索插入位置(35)标准 lower_bound
x 的平方根(69)答案在 [0, x]
寻找峰值(162)mid 与邻居比,往更大一侧走
搜索二维矩阵(74)拉平成一维二分或从右上/左下走
爱吃香蕉的珂珂(875)二分「速度」,check 能否吃完
分割数组的最大值(410)二分「最大子段和」,check 段数
寻找两个正序数组的中位数(4)二分较短数组的划分位置

迁移口诀:

「最小化最大值 / 最大化最小值」→ 二分答案 + check 函数;有序或旋转有序 → 二分下标。

模式 5:链表

必背操作

  • 虚拟头节点 dummy:简化头删、合并
  • 反转:prev / curr / next 三指针
  • 快慢指针:中点、环、倒数第 K

经典题 8:反转链表(206)

fun reverseList(head: ListNode?): ListNode? {
    var prev: ListNode? = null
    var curr = head
    while (curr != null) {
        val next = curr.next
        curr.next = prev
        prev = curr
        curr = next
    }
    return prev
}

经典题 9:合并两个有序链表(21)

思路:dummy 尾插,较小者接上;最后接上剩余段。

经典题 10:环形链表 II(142)

思路:快慢相遇后,slow 从头、fast 从相遇点同步走,相遇即环入口(距离关系推导)。

举一反三

变体题要点
两数相加(2)虚拟头 + 进位
删除链表的倒数第 N 个(19)快先走 N+1,删 slow.next
重排链表(143)找中点 → 反转后半 → 交替合并
K 个一组翻转链表(25)分组反转,记录组间连接
相交链表(160)双指针走 A+B / B+A 等长
排序链表(148)归并排序,找中点拆分

迁移口诀:

链表题先想 dummy;要改指向先保存 next;环/中点/倒数 → 快慢指针。

模式 6:栈与单调栈

核心思想

  • 栈:最近匹配、逆序处理、DFS 迭代
  • 单调栈:每个元素左右第一个更大/更小,O(n)

经典题 11:有效的括号(20)

思路:遇左括号入栈;遇右括号检查栈顶匹配。

经典题 12:每日温度(739)

思路:单调递减栈存下标;当前温度大于栈顶对应温度时弹出并算天数差。

经典题 13:柱状图中最大的矩形(84)

思路:单调递增栈;弹出时以弹出高度为高,宽度由当前 i 与栈顶下标算。

举一反三

变体题栈类型
最小栈(155)辅助栈同步最小值
逆波兰表达式(150)遇数字入栈,遇运算符弹两个
字符串解码(394)双栈:数字栈 + 字符串栈
接雨水(42)单调栈或双指针
滑动窗口最大值(239)单调递减队列
下一个更大元素 I(496)单调栈 + 哈希

迁移口诀:

「下一个更大/更小」→ 单调栈;嵌套结构 → 栈存状态。

模式 7:二叉树 DFS / BFS

DFS 模板(递归)

fun dfs(node: TreeNode?, ...) {
    if (node == null) return
    // 前序位置
    dfs(node.left, ...)
    // 中序位置
    dfs(node.right, ...)
    // 后序位置
}

BFS 模板(层序)

val queue = ArrayDeque<TreeNode>()
queue.add(root)
while (queue.isNotEmpty()) {
    val size = queue.size
    repeat(size) {
        val node = queue.removeFirst()
        // 处理 node
        node.left?.let { queue.add(it) }
        node.right?.let { queue.add(it) }
    }
}

经典题 14:二叉树的最大深度(104)

思路:1 + max(dfs(left), dfs(right)),后序位置聚合。

经典题 15:二叉树的最近公共祖先(236)

思路:后序;若 root 为 p 或 q 返回 root;左右都非空则 root 为 LCA。

经典题 16:二叉树层序遍历(102)

思路:BFS 按层 size 批量出队。

举一反三

变体题DFS / BFS
相同的树(100)同步 DFS 比较
翻转二叉树(226)交换左右递归
路径总和(112)前序减 target,叶节点判断
路径总和 III(437)前缀和 + HashMap(树上前缀和)
二叉搜索树验证(98)DFS 带 (min, max) 区间
将有序数组转换为 BST(108)递归中点作根
二叉树的右视图(199)BFS 每层最后一个
二叉树展开为链表(114)后序或 Morris

迁移口诀:

自底向上聚合 → 后序;路径问题 → 前序 + 回溯;按层 → BFS;BST → 中序或区间约束。

模式 8:回溯(Backtracking)

核心思想

DFS + 显式撤销选择,枚举所有合法方案。

模板

fun backtrack(path: MutableList<Int>, ...) {
    if (满足结束条件) {
        ans.add(path.toList())
        return
    }
    for (选择 in 选择列表) {
        if (剪枝) continue
        做选择
        backtrack(path, ...)
        撤销选择
    }
}

经典题 17:全排列(46)

思路:used 数组标记;每层选一个未使用的数。

经典题 18:子集(78)

思路:每个位置选或不选;或起点 start 递增选,避免重复。

经典题 19:组合总和(39)

思路:可重复选 → 递归时 start 从当前 i 开始,不回头。

举一反三

变体题剪枝要点
全排列 II(47)排序 + 同层去重 i > 0 && nums[i]==nums[i-1] && !used[i-1]
组合(77)只选 n 个,start 递增
组合总和 II(40)排序 + 同层去重,每个数用一次
括号生成(22)左 < n 可加左;右 < 左 可加右
单词搜索(79)网格 DFS + visited
N 皇后(51)列、主对角、副对角占用
分割回文串(131)切分 + 判断子串回文

迁移口诀:

「所有方案」→ 回溯;有重复元素 → 排序 + 同层去重;可重复选 → start 不从 0 重开。

模式 9:动态规划(DP)

识别条件

  1. 最优子结构
  2. 重叠子问题(记忆化或表格)
  3. 能写出状态转移方程

DP 解题四步

1. 定义状态 dp[i] / dp[i][j] 表示什么
2. 转移方程
3. 初始条件
4. 遍历顺序(保证依赖已计算)

经典题 20:爬楼梯(70)

dp[i] = dp[i-1] + dp[i-2],可压缩为两个变量。

经典题 21:最长递增子序列(300)

dp[i] = 以 i 结尾的 LIS 长度;内层 j < i 且 nums[j] < nums[i] 转移。
优化:耐心排序 + 二分 → O(n log n)。

经典题 22:零钱兑换(322)

dp[amount] = 凑 amount 最少硬币数;完全背包正向遍历。

经典题 23:最长公共子序列(1143)

if (s1[i]==s2[j]) dp[i][j] = dp[i-1][j-1] + 1
else dp[i][j] = max(dp[i-1][j], dp[i][j-1])

经典题 24:编辑距离(72)

增删改三种操作,dp[i][j] 为 s1[0..i) 到 s2[0..j) 最小编辑次数。

DP 子类与举一反三

子类代表题状态设计
线性 DP打家劫舍(198)dp[i] 与 i-1、i-2 关系
0-1 背包分割等和子集(416)dp[j] 能否凑重量 j,逆序遍历
完全背包完全平方数(279)正序遍历
区间 DP戳气球(312)dp[i][j] 开区间最优
状态机 DP买卖股票含冷冻期(309)持有/不持有/冷冻
树形 DP打家劫舍 III(337)节点返回 (抢, 不抢)
路径 DP不同路径(62)网格 dp[i][j]
字符串 DP最长回文子串(5)中心扩展或 dp[i][j]

迁移口诀:

方案数 → 加法转移;最值 → min/max;能否达到 → boolean;二维串 → 双串 DP;选或不选 → 背包。

模式 10:贪心

核心思想

每步做局部最优,需证明能推出全局最优(面试可说「交换论证」思路)。

经典题 25:跳跃游戏(55)

思路:维护能到达的最远位置 maxReach,遍历中若 i > maxReach 失败。

经典题 26:无重叠区间(435)

思路:按区间右端点排序,贪心选结束最早的,能留最多区间。

经典题 27:分发饼干(455)

思路:排序后双指针,小饼干满足小孩子。

举一反三

变体题贪心策略
跳跃游戏 II(45)当前步最远边界内选下一步最远
合并区间(56)按起点排序,能合并则扩右端点
用最少数量的箭引爆气球(452)同无重叠区间,按右端点
划分字母区间(763)记录各字符最后出现位置,扩展当前段
任务调度器(621)公式 (n+1)*(maxCount-1)+sameMax

模式 11:堆(优先队列)

核心思想

动态维护 TopK 或当前最值,插入删除 O(log n)。

经典题 28:数组中的第 K 个最大元素(215)

思路:大小为 K 的小顶堆;或快速选择 O(n) 平均。

经典题 29:合并 K 个升序链表(23)

思路:小顶堆存各链表头节点,每次弹出最小接上。

经典题 30:数据流的中位数(295)

思路:大顶堆存较小一半,小顶堆存较大一半,保持平衡。

举一反三

变体题堆用法
前 K 个高频元素(347)频次入堆
滑动窗口最大值(239)单调队列更优
查找和最小的 K 对数字(373)堆存 (sum, i, j)

模式 12:并查集(Union-Find)

模板

class UnionFind(n: Int) {
    private val parent = IntArray(n) { it }
    private val rank = IntArray(n)

    fun find(x: Int): Int {
        if (parent[x] != x) parent[x] = find(parent[x])
        return parent[x]
    }

    fun union(a: Int, b: Int): Boolean {
        val ra = find(a)
        val rb = find(b)
        if (ra == rb) return false
        if (rank[ra] < rank[rb]) parent[ra] = rb
        else {
            parent[rb] = ra
            if (rank[ra] == rank[rb]) rank[ra]++
        }
        return true
    }
}

经典题 31:省份数量(547)

思路:邻接矩阵,遍历 union(i,j),数根节点个数。

经典题 32:冗余连接(684)

思路:加边时若两端已连通则该边冗余。

举一反三

变体题并查集作用
岛屿数量(200)DFS/BFS 也可;并查集合并陆地
账户合并(721)按邮箱 union
最长连续序列(128)也可用 Set,并查集合并相邻数字

模式 13:图 BFS / DFS

经典题 33:岛屿数量(200)

思路:遍历网格,'1' 则 dfs 沉岛(标记 visited)并 count++。

经典题 34:课程表(207)

思路:拓扑排序,BFS 入度为 0 或 DFS 三色标记判环。

举一反三

变体题方法
腐烂的橘子(994)多源 BFS
单词接龙(127)BFS 最短路径
网络延迟时间(743)Dijkstra 或 BFS+堆

模式 14:位运算

常用技巧

技巧式子
取最低位 1x & (-x)
去掉最低位 1x & (x - 1)
判断 2 的幂x > 0 && (x & (x-1)) == 0
异或性质a^a=0, a^0=a,可消重复

经典题 35:只出现一次的数字(136)

思路:全体异或。

经典题 36:位 1 的个数(191)

思路:n & (n-1) 直到为 0。

举一反三

变体题技巧
缺失数字(268)0..n 异或
汉明距离(461)x xor y 再数 1
颠倒二进制位(190)逐位取出

四、经典必刷题单(按优先级)

4.1 第一梯队:必须熟练(各模式代表)

题号题目模式
1两数之和哈希
3无重复字符的最长子串滑动窗口
15三数之和双指针
20有效的括号栈
21合并两个有序链表链表
53最大子数组和DP / 贪心
70爬楼梯DP
76最小覆盖子串滑动窗口
102二叉树层序遍历BFS
104二叉树最大深度DFS
121买卖股票的最佳时机DP
142环形链表 II快慢指针
146LRU 缓存哈希 + 双向链表
200岛屿数量DFS/BFS
206反转链表链表
215数组第 K 个最大堆
236二叉树最近公共祖先树 DFS
322零钱兑换完全背包
347前 K 个高频元素堆
416分割等和子集0-1 背包

4.2 第二梯队:高频加深

题号题目模式
11盛最多水的容器双指针
33搜索旋转排序数组二分
42接雨水双指针 / 单调栈
46全排列回溯
56合并区间排序 + 贪心
78子集回溯
79单词搜索回溯
84柱状图最大矩形单调栈
128最长连续序列哈希 Set
139单词拆分DP
141环形链表快慢指针
148排序链表归并
152乘积最大子数组DP
198打家劫舍线性 DP
207课程表拓扑
239滑动窗口最大值单调队列
240搜索二维矩阵 II分治走指针
279完全平方数完全背包
300最长递增子序列DP
322零钱兑换DP
437路径总和 III树 + 前缀和
438找到字母异位词滑动窗口
560和为 K 的子数组前缀和 + 哈希
739每日温度单调栈
1143最长公共子序列双串 DP

4.3 第三梯队:架构 / 高级岗位加分

题号题目说明
4寻找两个正序数组中位数二分划分
23合并 K 个升序链表堆
25K 个一组翻转链表链表难点
32最长有效括号栈 / DP
72编辑距离经典二维 DP
84柱状图中最大的矩形单调栈经典
124二叉树最大路径和树形 DP
128最长连续序列O(n) 思维
146LRU 缓存设计题必考
295数据流中位数双堆
312戳气球区间 DP

五、举一反三方法论(如何从一题扩展到一类)

5.1 四步迁移法

1. 抽象原题:我在「枚举什么」?瓶颈是什么?
2. 识别结构:有序?连续?树?选或不选?
3. 换约束:个数变 K、重复变不可重复、最大变最小
4. 换数据结构:哈希 → 排序双指针;DFS → BFS;数组 → 树

5.2 经典迁移链(建议整链练习)

链 A:两数之和 → 三数之和 → 四数之和 → 最接近的三数之和

哈希 O(n)     →  排序+双指针 O(n²)  →  多一层循环  →  维护最小差值

链 B:爬楼梯 → 打家劫舍 → 打家劫舍 II(环)→ 打家劫舍 III(树)

线性递推  →  不能相邻  →  首尾特殊  →  树形返回双状态

链 C:子集 → 组合 → 排列 → 含重复元素的去重

start 递增  →  固定长度  →  used 标记  →  排序+同层剪枝

链 D:最大子数组和 → 乘积最大子数组 → 环形子数组和

Kadane  →  维护 min/max 乘积  →  总和减最小子数组和

链 E:反转链表 → K 组翻转 → 重排链表 → 合并 K 链表

单组反转  →  分段  →  找中点+反转+合并  →  堆优化

5.3 面试官追问时的升级路径

初始解法追问升级方向
暴力 O(n²)能否 O(n)?哈希、双指针、单调栈
O(n) 额外数组能否 O(1) 空间?原地交换、读写指针
递归 DFS数据很大栈溢出?改迭代 + 显式栈
TopK 排序 O(n log n)能否更快?堆 O(n log k) 或快选 O(n)

六、复杂度速查

操作平均最坏
HashMap get/putO(1)O(n)
快排O(n log n)O(n²)
堆 push/popO(log n)O(log n)
二分O(log n)O(log n)
DFS/BFS 图O(V+E)O(V+E)

空间复杂度常见来源:哈希 O(n)、递归栈 O(h)、BFS 队列 O(w)、DP 表 O(n) 或 O(n²)。


七、手写代码注意事项

7.1 边界清单(写完必查)

□ 空输入:null、[]、"" 
□ 单元素
□ 两元素极端
□ 重复元素
□ 整数溢出(Kotlin 一般无此问题,Java 需注意)
□ 链表:空、单节点、环
□ 树:空树、单支、只有左/右

7.2 面试沟通模板

1. 复述题意 + 确认输入输出与约束
2. 举例:正常 case + 边界 case
3. 暴力思路 → 瓶颈 → 优化思路
4. 写代码(主逻辑优先,边界可后补)
5. 口述复杂度
6. 主动提测试用例走一遍

7.3 Android 面试常见语言

  • Kotlin:社招 Android 越来越多,本文代码以 Kotlin 为例
  • Java:老牌大厂笔试仍常见,语法与 Kotlin 思路一致
  • 建议:同一模板用一门语言练熟,另一门能看懂即可

八、八周刷题计划

第 1~2 周:基础模式

天内容题(LeetCode 号)
1-2哈希1, 217, 49
3-4双指针15, 11, 26
5-6滑动窗口3, 209, 438
7复盘重做错题

第 3~4 周:链表 + 栈 + 二分

天内容题
1-2链表206, 21, 141, 142
3-4栈20, 155, 739
5-6二分33, 34, 35
7复盘

第 5~6 周:树 + 回溯

天内容题
1-3树 DFS/BFS104, 102, 236, 98
4-6回溯46, 78, 39, 22
7复盘

第 7~8 周:DP + 贪心 + 综合

天内容题
1-2线性 DP70, 198, 53, 152
3-4背包322, 416, 139
5贪心55, 56, 435
6堆 / 并查集215, 347, 200
7-8模拟面试146, 76, 72 任选

九、设计类常考题

9.1 LRU 缓存(146)

思路:HashMap<key, Node> + 双向链表;get/put 时把节点移到头部;超容量删尾部。

举一反三:LFU 缓存(460)→ 多一个频次维度 + 每层双向链表。

9.2 Min Stack(155)

思路:数据栈 + 辅助栈同步压入当前最小值。

9.3 实现 Trie(208)

思路:子节点数组/Map,isEnd 标记;前缀树支撑自动补全、单词搜索 II。


十、与 Android 开发的联系(面试加分表述)

算法模式工程场景
LRUBitmap 缓存、网络图片库
拓扑排序模块依赖、任务编排
并查集连通性、分组
滑动窗口埋点窗口统计、限流
堆优先级任务队列
双指针归并、去重、Diff 类思路
位运算权限 flag、状态位掩码

能在答完题后补一句工程关联,会体现 学以致用,尤其适合 Android 架构岗。


十一、最终应达到的水平

合格的面试算法能力:

  • 见到 medium 题 10~15 分钟内 说出正确模式
  • 第一梯队 20 题 能独立手写无重大 bug
  • 能口述 时间空间复杂度 并给出优化方向
  • 能 举一反三:同类变体换约束后知道改哪里
  • 代码 边界完整,沟通清晰

十二、最短路径

1. 背熟第二节「题型识别总表」
2. 精做第三节每个模式的「经典题 1」
3. 按第四节第一梯队 20 题过关
4. 每题写三行:识别信号 / 模板 / 一个变体
5. 第八节八周计划或考前集中二刷

一句话总结:

面试算法不是背 500 道题,而是掌握 十几种模式 + 经典题锚点 + 举一反三的迁移链。

附录:LeetCode 题号速查索引

模式题号
哈希1, 49, 128, 217, 347, 560
双指针11, 15, 26, 42, 88, 125, 167, 283
滑动窗口3, 76, 209, 239, 438, 567
二分33, 34, 35, 69, 74, 162, 875
链表19, 21, 23, 141, 142, 148, 206, 234
栈20, 84, 155, 394, 739, 84
树94, 98, 100, 102, 104, 105, 114, 199, 226, 236, 297
回溯17, 22, 39, 40, 46, 47, 51, 78, 79, 131
DP5, 53, 62, 70, 72, 121, 139, 152, 198, 279, 300, 322, 416, 1143
贪心45, 55, 56, 122, 435, 452, 621, 763
堆23, 215, 295, 347, 373
并查集200, 547, 684, 721
图127, 200, 207, 994, 743
位运算136, 190, 191, 268, 461
设计146, 155, 208, 460

英文学习视频推荐路径

从启蒙动画到正常英美影片,按难度循序渐进。


第一阶段:启蒙动画(零基础 → 入门)

特点:语速慢、词汇简单、重复率高、画面辅助理解

推荐说明
Peppa Pig(小猪佩奇)语速极慢,每集 5 分钟,日常对话,适合纯入门
Bluey(布鲁伊)澳洲家庭生活,语速稍快于佩奇,剧情有趣
Maisy Mouse(小鼠波波)几乎没对话,旁白为主,零基础友好
Dora the Explorer(爱探险的朵拉)互动式教学,会教单词和短语

第二阶段:进阶动画(入门 → 初级)

特点:有完整故事线,词汇量扩大,语速正常偏慢

推荐说明
The Adventures of Tintin(丁丁历险记)冒险题材,对话清晰,BBC 出品
Avatar: The Last Airbender(降世神通)剧情优秀,语言地道,适合口语学习
Gravity Falls(怪诞小镇)幽默+悬疑,青少年向,词汇实用
The Simpsons(辛普森一家)经典美式幽默,文化梗多,初级以上

第三阶段:生活情景剧(初级 → 中级)

特点:真实生活场景,日常口语,适合模仿跟读

推荐说明
Friends(老友记)经典中的经典,对话清晰,适合精听跟读
The Office (US)(办公室)职场英语,语速适中,幽默感强
Modern Family(摩登家庭)多口音、多年龄段,话题丰富
How I Met Your Mother(老爸老妈浪漫史)类似老友记,现代感更强

第四阶段:纪录片 / 访谈(中级)

特点:旁白标准清晰,信息密度高,适合积累词汇

推荐说明
BBC Earth / Planet Earth(地球脉动)英音旁白,语速慢,词汇正式
TED Talks(TED 演讲)15 分钟左右,话题多样,有字幕
The Crown(王冠)英音,正式优雅,适合练英式英语
Abstract: The Art of Design(抽象:设计的艺术)设计相关,语速适中,适合科技从业者

第五阶段:正常英美影片(中高级 → 流利)

特点:正常语速,各种口音,习惯用语,文化背景

推荐说明
The Social Network(社交网络)科技相关,对话密集,适合 tech 从业者
The Martian(火星救援)科技+独白,发音清晰
Silicon Valley(硅谷)剧集,科技圈文化,梗多
The West Wing(白宫风云)语速极快,逻辑性强,适合进阶挑战
Sherlock(神探夏洛克)英音,语速快,适合听力挑战

学习方法建议

1. 第一遍: 开中文字幕,看懂剧情
2. 第二遍: 开英文字幕,跟读模仿
3. 第三遍: 关字幕,纯听,看能听懂多少
4. 反复看同一集,直到能跟着说出台词

推荐工具

  • 网易公开课 — TED、纪录片
  • Bilibili — 大量带双语字幕的影视资源
  • Netflix / Disney+ — 原生英文字幕+插件
  • YouTube — 订阅英文博主,自动生成字幕

从 Peppa Pig 开始,到 Friends 过渡,最后到 Silicon Valley / The Social Network 收尾,这条路径下来基本可以达到日常交流无障碍。

Android 开发者在 AI 时代的进阶路线

核心思路:不要转行,要升级

现有 Android 开发经验是宝贵的基础,不是包袱。关键是把技能树往 AI 时代的方向往上叠,而不是从零开始。


阶段一:加固护城河(现在 ~ 3 个月)

目标:让自己在 Android 领域不可被 AI 轻易替代

方向具体做什么
深入底层Framework、Binder、AMS/WMS、SurfaceFlinger、性能优化(卡顿、内存、启动速度)
NDK / C++音视频、图形渲染、游戏引擎、性能敏感模块
跨端架构Compose Multiplatform、KMP,能一套代码跑 Android + iOS + Desktop
工具链把 AI 变成你的生产力工具——Cursor/Claude/Copilot 写代码、自动化测试、代码审查
AI 现阶段能替代的是"写常规业务逻辑的 Android 开发",替代不了搞系统底层、性能优化、跨端架构的人。

阶段二:拓展 AI 能力(3 ~ 6 个月)

目标:让自己成为"懂 AI 的 Android 开发"

  • AI 模型落地:学习如何在 Android 端部署和运行 AI 模型(ML Kit、TensorFlow Lite、ONNX Runtime、Google AI Edge)
  • 端侧 AI 应用:做 1~2 个落地的 demo——图片分类、OCR、语音识别、AI 修图等
  • AIGC 集成:了解如何通过 API 集成大模型(调用 LLM、RAG、Streaming 输出)
  • Agent 开发:了解 AI Agent 的概念,未来 Android 上的 Agent 应用会越来越多

阶段三:拓宽视野(6 ~ 12 个月)

目标:从一个 Android 开发变成"移动端全栈 + AI 产品"

方向原因
Flutter / Compose Multiplatform一套代码多端跑,降本增效,大厂在推
后端基础(Go / Kotlin + Ktor)能独立做全栈,做 AI 应用通常需要后端配合
AI 产品思维理解"AI 能解决什么实际问题",比纯写代码更值钱

阶段四:定位未来方向(12 个月+)

可选路径

  1. 端侧 AI 专家(最契合 Android 背景)

    • 端侧模型部署、优化、量化
    • 手机厂商(小米、OPPO、vivo、华为)都在砸钱做端侧 AI
  2. AI Native 应用开发

    • 做 AI 助手、AI 工具类 App
    • 独立开发者路线,做产品出海
  3. 跨平台架构师

    • 主导 KMP / Compose Multiplatform 架构
    • 移动端 + 桌面端 + Web 统一架构设计
  4. 进入 AI 公司做应用层

    • 加入 AI 创业公司或大厂 AI 部门
    • 价值在于"把 AI 能力做成好用的产品"

每周行动清单

周一 ~ 周三: 刷 LeetCode + 学 Android 底层(每天 1 小时)
周四: 学 AI 知识(端侧模型/ML Kit),做小实验
周五: 看行业动态,了解 AI 工具,优化自己的工具链
周末: 做一个小的 side project,把当周学的东西用起来

总结

不要跟 AI 比写代码,要比 AI 更懂系统、更懂架构、更懂产品。Android 经验是地基,往上叠 AI 能力,就是未来最值钱的人。

技术管理 / Team Lead 进阶路线

定位:从"个人贡献者(IC)"到"能带团队、担责任、建立信任"的管理方向。
适用对象:4 年以上 Android/移动开发,具备一定技术深度,希望转向技术管理路径。
抗替代性逻辑:管理的核心是责任承担 + 信任关系——团队出问题谁负责、员工绩效谁评估、跨部门冲突谁协调,这些都需要"自然人"承担后果并建立长期信任,AI 可以辅助分析数据、给建议,但不能代替你签字、代替你和人建立信任关系。

一、先想清楚:要不要走管理路线

1.1 技术管理 ≠ 技术能力的延伸奖励

常见误区:"我技术最好,所以该我带队"
现实情况:管理是一种不同的能力(沟通、协调、评估他人、承担责任),
         技术好只是"入场门槛",不是"胜任证明"

1.2 自我评估问题

- 我是否愿意把大量时间从"写代码"转向"开会、沟通、评审、协调"?
- 我是否能接受"团队成绩优先于个人技术炫技"?
- 我是否能在冲突中做出让部分人不满意但对整体最优的决定?
- 我是否愿意承担"团队犯错,我担责"的压力?

如果这些问题的答案偏向犹豫,可以考虑"技术专家/架构师"路线(见 02-架构设计与技术选型学习路线.md)而非纯管理路线,两条路线也可以在很多公司并行发展(双通道)。


二、能力地图

能力域内容
团队管理基础招聘、绩效评估、一对一沟通、团队氛围
项目管理排期、风险管理、跨团队协调
技术判断与授权既要懂技术能评审方案,又要学会放手让团队做
向上管理与向下管理与上级对齐目标,向团队传达清晰方向
人才培养Code Review 文化、导师制、晋升评估
危机处理线上事故、团队冲突、人员流失应对

三、学习路线总览(建议 12~18 个月,多数需在实际管理岗位中历练)

阶段 0:管理心态转换与基础认知          → 1~2 月
阶段 1:一对一沟通与团队氛围建设        → 2 月
阶段 2:项目管理与风险控制              → 2~3 月
阶段 3:技术判断与授权平衡              → 3 月
阶段 4:绩效评估与人才培养              → 2~3 月
阶段 5:向上管理与跨部门协作            → 2 月
阶段 6:危机处理与团队文化建设          → 持续

重要提示:管理能力必须在真实带人场景中历练,看书/上课只能建立框架认知,无法替代实践。建议先争取 Tech Lead(带 2~3 人的小团队/项目)过渡,再考虑正式 Team Lead/EM。


四、阶段 0:管理心态转换与基础认知(1~2 月)

4.1 IC 思维 vs 管理者思维

维度IC(个人贡献者)管理者
成功标准自己代码质量高、任务完成好团队整体产出好,即使自己不写代码
时间分配大部分时间写代码大部分时间沟通、评审、协调
决策方式自己拿主意授权他人拿主意,自己把关方向
成长指标技术深度团队成长速度、组织效能

4.2 阶段产出

  • [ ] 写一页《我为什么想做管理》,明确动机(而非"技术卷不动了才想转管理")
  • [ ] 找一位在职管理者做一次深度访谈,了解真实日常

五、阶段 1:一对一沟通与团队氛围建设(2 月)

5.1 一对一(1:1)会议框架

频率:建议每 1~2 周一次,每次 30 分钟
内容结构:
  1. 近期工作进展与困难(员工主导)
  2. 职业发展与成长诉求
  3. 对团队/管理的反馈(营造安全说真话的氛围)
  4. 管理者的观察与反馈

5.2 常见沟通技巧

场景技巧
给负面反馈具体事实 + 影响 + 期望改进,避免人格评价
员工抱怨先倾听理解,再判断是否需要行动,不要急于辩解
冲突调解分别了解双方视角,找到共同目标而非站队

5.3 阶段产出

  • [ ] 完成至少 4 次结构化 1:1(可先在带教/mentor 场景中练习)
  • [ ] 写一份《团队氛围观察笔记》:目前团队士气、主要问题

六、阶段 2:项目管理与风险控制(2~3 月)

6.1 排期与风险管理

排期原则:
- 留缓冲(Buffer),不按理想情况排满
- 识别关键路径(哪个任务卡住会拖累整体)
- 定期检查点,而非等到 deadline 才发现问题

风险管理:
- 提前识别技术风险(新技术/新架构不确定性)
- 提前识别人员风险(关键人员请假/离职)
- 建立"提前预警"机制,而非"出了问题才上报"

6.2 跨团队协调

- 明确依赖关系:我们依赖谁,谁依赖我们
- 提前沟通排期冲突,而非临期才发现
- 建立跨团队的责任边界文档,减少"扯皮"

6.3 阶段产出

  • [ ] 主导或参与过至少 1 个跨团队协调的项目排期
  • [ ] 写一份《项目风险清单模板》并在真实项目中使用

七、阶段 3:技术判断与授权平衡(3 月)

7.1 管理者要不要懂技术细节

必须懂到能:
- 评估技术方案的合理性,提出关键问题
- 在团队意见分歧时,理解双方的技术论点
- 识别"这个技术决策有没有被过度简化/夸大风险"

不需要懂到能:
- 自己写出最优实现(这是团队成员的工作)
- 事无巨细地审查每一行代码

7.2 授权的艺术

过度控制的信号:什么都要过一遍、不放心让别人做决定
过度放手的信号:完全不参与技术决策、出问题才知道

平衡点:
- 明确哪些决策必须经过你(架构级、跨团队影响大的)
- 哪些决策完全授权(局部实现细节)
- 建立"决策权限清单",团队和你自己都清楚边界

7.3 阶段产出

  • [ ] 写一份《团队决策权限清单》:哪些事项需要报备、哪些完全授权
  • [ ] 完成至少 1 次"放手让团队自己决定"并观察结果的实践

八、阶段 4:绩效评估与人才培养(2~3 月)

8.1 绩效评估原则

- 基于事实和产出,而非印象和亲疏
- 提前沟通预期,而非考核时才第一次提出问题
- 区分"能力问题"和"意愿问题",处理方式完全不同

8.2 人才培养机制

机制内容
Code Review 文化不只是找 Bug,也是知识传递和培养机会
导师制给新人/初级成员明确的带教对象
晋升路径透明化让团队成员清楚"做到什么程度可以晋升"
成长型任务分配有意识地把有挑战性的任务分给需要成长的人

8.3 阶段产出

  • [ ] 完成至少 1 次正式绩效评估(含书面反馈)
  • [ ] 建立 1 套团队 Code Review 规范
  • [ ] 带教至少 1 名初级/新人成员并有可见成长记录

九、阶段 5:向上管理与跨部门协作(2 月)

9.1 向上管理

- 主动同步进展,不要让上级"来问才知道"
- 汇报要有结论和建议,不只是罗列问题
- 提前预警风险,给上级留出应对时间

9.2 向下传达目标

- 把公司/部门的战略目标翻译成团队能理解、能执行的具体任务
- 解释"为什么"而不只是"做什么",提升团队认同感

9.3 阶段产出

  • [ ] 完成一次向上汇报(如季度回顾),得到明确反馈
  • [ ] 写一份《团队目标翻译文档》:把上层目标拆解为团队任务

十、阶段 6:危机处理与团队文化建设(持续)

10.1 常见危机场景

场景处理原则
线上重大事故先止损,再追责,最后复盘防再发
核心人员离职提前识别风险信号,做好知识传承与交接
团队内部冲突及时介入,避免拖成长期士气问题
业务方强压排期用数据和风险说话,而非硬顶或硬答应

10.2 团队文化建设

文化不是喊口号,是通过日常决策体现出来的:
- 你在紧急情况下的选择,比平时说的话更能定义文化
- 对错误的态度(惩罚 vs 学习型复盘)决定团队是否敢创新
- 对"说真话"的鼓励程度决定团队信息是否透明

10.3 阶段产出

  • [ ] 处理过至少 1 次真实的团队冲突或危机场景并复盘
  • [ ] 写一份《我理想的团队文化》文档并在实践中验证调整

十一、简历/晋升表述框架

不要写:「负责团队管理工作」
要写:
「带领 X 人团队完成 XX 项目,通过建立每周风险检查点机制将项目延期率
从 XX% 降至 XX%;建立 Code Review 规范和晋升路径透明化机制,
团队半年内主动流失率为 0,2 名成员完成晋升。」

十二、能力自检清单(20 项)

打勾 ≥ 14 项,说明已具备基础管理能力:

基础认知

  • [ ] 能清楚说出自己想做管理的真实动机
  • [ ] 理解 IC 思维和管理者思维的本质差异

沟通

  • [ ] 能做结构化的 1:1 沟通
  • [ ] 能给出具体、非人格化的负面反馈
  • [ ] 处理过至少 1 次团队冲突

项目管理

  • [ ] 主导过跨团队项目排期
  • [ ] 有风险清单模板并实际使用

技术判断

  • [ ] 能评估技术方案而不需要事事亲自实现
  • [ ] 有清晰的团队决策权限边界

人才培养

  • [ ] 完成过正式绩效评估
  • [ ] 带教过至少 1 名成员并有成长记录
  • [ ] 建立过 Code Review 或晋升相关机制

向上/跨部门

  • [ ] 完成过向上汇报并获得明确反馈
  • [ ] 能把上层目标翻译成团队任务

危机与文化

  • [ ] 处理过至少 1 次真实危机场景
  • [ ] 有清晰的团队文化主张并能举例说明如何体现

结果

  • [ ] 有可量化的团队产出改善数据
  • [ ] 团队成员流失率/满意度有正向变化证据

十三、常见误区

误区正确认知
技术最强的人最该带团队管理是不同能力,需要单独学习和练习
管理就是分配任务核心是沟通、信任建设和责任承担
事事都要亲自把关过度控制会抑制团队成长,需要学会授权
绩效评估凭印象必须基于事实和提前沟通的预期
团队文化靠开会宣传文化由日常真实决策体现,不是喊口号

十四、最短路径

1. 明确自己的管理动机,理解 IC vs 管理者思维差异(1个月)
2. 争取 Tech Lead 或小团队带教机会,开始实践 1:1 沟通(3个月)
3. 主导 1 次跨团队项目排期与风险管理(3个月)
4. 建立团队决策权限清单,练习授权(2个月)
5. 完成至少 1 次正式绩效评估周期,积累管理实践案例

一句话总结:

技术管理的护城河是"责任承担 + 长期信任关系",这是 AI 能提供建议、但不能代替你和真实的人建立关系、也不能代替你承担团队后果的领域。

十五、关联文档

  • 02-架构设计与技术选型学习路线.md — 若更倾向技术深度而非管理,可参考此路线
  • ../Android高级架构师学习路线.md — 技术领导力章节的补充
  • ../Android移动开发方向抗替代性与薪酬分析.md — 替代率与薪酬定位

移动安全 / 逆向分析学习路线

定位:从"会用 Android"到"能分析、攻防、评审移动安全机制"的方向,是移动开发方向中抗替代性最强的分支之一。
适用对象:3 年以上 Android 开发,希望转向移动安全测试/研究方向。
抗替代性逻辑:安全领域天然是攻防对抗,训练数据稀少且持续变化(新漏洞类型没有历史语料),出错需要"自然人担责"(安全签字、漏洞评级),AI 只能辅助分析已知模式,无法独立完成 0day 挖掘和责任判断。
完整详细版:本文是精简导航版,完整分阶段路线(面向资深岗位,含 TEE/虚拟化/评审标准等)见 ../资深系统安全工程师-学习路线.md,两文档配合使用。

一、能力地图

能力域内容
信任链与系统安全架构Verified Boot、SELinux、沙箱、权限模型
静态/动态分析APK 逆向、Hook 技术、协议分析
常见漏洞类型组件暴露、权限绕过、Intent 劫持、注入类
加密与密钥管理TEE、Keystore、常见密码学误用模式
安全评审与标准威胁建模、SDL 流程、评审清单

二、学习路线总览(建议 12~20 个月,转型者节奏)

阶段 0:密码学与信任边界基础            → 1 月
阶段 1:Android 安全架构精讲            → 2~3 月
阶段 2:静态分析实战(逆向基础)        → 2 月
阶段 3:动态分析实战(Hook/调试)       → 2~3 月
阶段 4:常见漏洞类型与漏洞分析报告      → 2~3 月
阶段 5:进阶专题(TEE/内核保护,选修)  → 3~4 月
阶段 6:项目化与求职                    → 持续

三、阶段 0:密码学与信任边界基础(1 月)

3.1 必学概念

机密性、完整性、身份认证、不可抵赖 —— 四大安全目标
对称加密(AES) / 非对称加密(RSA/ECC) / 哈希(SHA-256) / HMAC / AEAD(GCM)
数字证书、证书链、根证书与信任锚

3.2 阶段产出

  • [ ] 写一页笔记:四大安全目标各用什么机制实现
  • [ ] 能画出证书链验证的基本流程

四、阶段 1:Android 安全架构精讲(2~3 月)

4.1 信任链(背诵级)

BootROM → Bootloader(验证下一阶段签名)
  → Verified Boot / AVB(验证系统分区完整性)
  → dm-verity(运行时验证系统分区未被篡改)
  → Kernel(SELinux 强制访问控制)
  → init → Zygote → SystemServer
  → 应用沙箱(UID隔离、SELinux domain)

4.2 核心机制

机制作用
SELinux强制访问控制(MAC),限制进程能访问的资源
应用沙箱每个应用独立 UID,默认互不可见
权限模型安装时权限 + 运行时权限 + 特殊权限分级
Keystore/TEE密钥硬件隔离存储,防止提取

4.3 阶段产出

  • [ ] 画一张完整信任链图,标注每层由谁验证
  • [ ] 能看懂 SELinux 拒绝日志(avc: denied)并定位原因
  • [ ] 默写 Verified Boot、dm-verity、SELinux、TEE、Keystore 的一句话定义

五、阶段 2:静态分析实战(2 月)

5.1 工具链

工具用途
jadxAPK 反编译为可读 Java 代码
apktool资源与 Manifest 反编译/重打包
MobSF自动化静态扫描平台
Ghidra/IDA(进阶)Native 层 So 库逆向

5.2 分析要点

1. AndroidManifest.xml:暴露的组件(exported=true)、权限声明
2. 关键字符串/常量:API Key、Base URL、加密密钥硬编码
3. 网络请求逻辑:是否有证书校验绕过风险
4. 加密实现:是否使用弱算法、密钥是否硬编码

5.3 阶段产出

  • [ ] 独立分析至少 3 个 APK(可用公开靶场应用,如 OWASP MSTG 提供的练习 App)
  • [ ] 输出《静态分析发现清单》:暴露组件、潜在硬编码密钥等

六、阶段 3:动态分析实战(2~3 月)

6.1 核心工具

工具用途
Frida运行时 Hook,动态修改行为、绕过校验
drozer组件级攻击面测试(暴露的 Activity/Service/Provider)
Burp Suite / mitmproxy网络流量分析与篡改测试
objection基于 Frida 的免 root/简化操作工具

6.2 典型练习

// Frida Hook 示例:绕过简单 SSL Pinning 检测(仅用于授权测试环境)
Java.perform(function () {
    var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
    // Hook 逻辑用于学习理解证书校验机制
});

重要原则:所有动态分析练习必须在自己搭建的靶场应用或授权的 CTF/众测环境中进行,不得对未授权的真实线上系统测试。

6.3 阶段产出

  • [ ] 用 Frida 完成至少 3 次运行时 Hook 练习(在授权靶场环境)
  • [ ] 用 drozer 完成一次组件暴露面测试

七、阶段 4:常见漏洞类型与漏洞分析报告(2~3 月)

7.1 移动端常见漏洞分类

类型说明
组件暴露Activity/Service/Provider 未做权限校验被外部调用
Intent 劫持隐式 Intent 被恶意应用截获
权限绕过逻辑漏洞导致越权访问
不安全存储敏感数据明文存储在 SharedPreferences/外部存储
弱加密实现ECB 模式、硬编码密钥、自研弱算法
WebView 漏洞JS 接口暴露过度、任意文件访问

7.2 漏洞分析报告模板

标题:[漏洞名称]

原理:
- 漏洞成因,涉及的机制原理

复现步骤:
- 环境搭建、触发条件、复现过程(在授权环境中)

影响面:
- 该漏洞可能造成的实际危害

修复建议:
- 具体的代码/配置层面修复方案

7.3 阶段产出

  • [ ] 复现至少 2 个公开 CVE 或 CTF 题目并写出完整分析报告
  • [ ] 完成至少 1 份《本机应用攻击面清单》(基于公开信息与合法测试)

八、阶段 5:进阶专题(选修,3~4 月)

专题内容
TEE / Keystore / StrongBox支付安全方向必学
AVF / pKVM 虚拟化隔离车载/高端终端方向
内核漏洞利用与缓解机制偏研究方向,周期长
隐私工程数据最小化、匿名化、合规要求

详细展开见 ../资深系统安全工程师-学习路线.md 阶段 2~6。


九、阶段 6:项目化与求职

9.1 必须产出(安全岗最看重)

  1. 漏洞分析报告 3 份以上(原理→复现→修复建议)
  2. 一个自动化工具(APK 静态扫描脚本、Frida Hook 工具集),放 GitHub
  3. 一次内部分享/博客,讲清一个安全机制

9.2 求职路径

路径说明
内部转岗现公司有安全团队优先尝试,风险最低
社招安全测试/移动安全工程师比"安全研究员"门槛低,转型第 1~2 年优先
红队/漏洞研究员门槛更高,回报也更高,需有 CTF/漏洞挖掘作品

认证参考:OSCP(渗透测试)、CISSP(偏管理),作品和实战报告比证书更重要。


十、能力自检清单(20 项)

打勾 ≥ 14 项,说明已建立移动安全实质能力:

基础

  • [ ] 能讲清 Android 完整信任链
  • [ ] 能看懂 SELinux 拒绝日志并定位原因
  • [ ] 默写五大安全机制的一句话定义

静态分析

  • [ ] 用 jadx/apktool 独立分析过 3 个以上 APK
  • [ ] 能识别 Manifest 中的高风险暴露组件
  • [ ] 能发现硬编码密钥等常见静态问题

动态分析

  • [ ] 用 Frida 完成过运行时 Hook 练习
  • [ ] 用 drozer 完成过组件攻击面测试
  • [ ] 理解常见网络层安全测试方法

漏洞分析

  • [ ] 复现过至少 2 个公开 CVE
  • [ ] 写过完整《原理-复现-修复建议》报告
  • [ ] 理解至少 6 种常见移动端漏洞类型

进阶(可选)

  • [ ] 理解 TEE 与 Keystore 的职责划分
  • [ ] 了解虚拟化隔离基本概念

产出与表达

  • [ ] GitHub 有 1 个安全相关工具/脚本
  • [ ] 做过至少 1 次安全技术分享
  • [ ] 简历能写出"移动开发+安全"复合项目经历

软实力

  • [ ] 能举出一次"我拍板并承担后果"的安全判断
  • [ ] 理解安全测试的授权边界与合规要求

十一、常见误区

误区正确认知
在未授权系统上做安全测试必须在自建靶场或授权环境练习,法律风险不可忽视
只学工具不懂原理面试和实战都要求解释"为什么",不只是"怎么用工具"
证书比实战报告重要招聘更看重复现报告和工具产出
安全等于渗透测试安全还包括架构设计评审、隐私工程等更广领域

十二、最短路径

1. 补齐密码学与信任链基础(1个月)
2. 精讲 Android 安全架构,默写核心机制(2个月)
3. 静态分析 3 个 APK + 动态分析 Hook 练习(4个月)
4. 复现 2 个 CVE,写完整分析报告(3个月)
5. 产出 1 个开源工具,整理作品集求职

一句话总结:

移动安全的护城河是"攻防对抗 + 稀缺数据 + 责任判断"三重壁垒,AI 能辅助分析已知模式,但无法替你在授权环境中完成真实复现与责任判断。

十三、关联文档

  • ../资深系统安全工程师-学习路线.md — 完整详细版(面向资深岗位)
  • ../Linux内核学习路线.md — 内核保护机制基础
  • ../Android移动开发方向抗替代性与薪酬分析.md — 替代率与薪酬定位
  • ../传音推荐.md — 手机厂商真实安全岗位 JD 参考