Hot100:二叉树的中序遍历(Binary Tree Inorder Traversal)递归 / 显式栈 ACERS 解析

副标题 / 摘要 二叉树遍历是树题模板的起点,中序遍历则是“递归思维”和“显式栈模拟”最典型的一题。本文按 ACERS 结构拆解 LeetCode 94,把左-根-右的访问顺序、迭代栈写法和工程迁移价值一次讲清。 预计阅读时长:10~12 分钟 标签:Hot100、二叉树、DFS、栈、中序遍历 SEO 关键词:Hot100, Binary Tree Inorder Traversal, 二叉树的中序遍历, 中序遍历, 显式栈, LeetCode 94 元描述:从递归到显式栈,系统讲透 LeetCode 94 二叉树中序遍历,并给出工程场景迁移与多语言实现。 目标读者 正在刷 Hot100,希望把树遍历模板固定下来的同学 刚从数组 / 链表过渡到树结构,容易把前序、中序、后序顺序写混的开发者 需要在 BST、表达式树、抽象语法树里复用“左-根-右”思想的工程师 背景 / 动机 中序遍历本身不复杂,但它的训练价值很高: 它是“递归 = 隐式栈,迭代 = 显式栈”最容易建立直觉的一题 它能帮助你稳定掌握“先一路向左,再回退访问根,再转向右子树”的过程 在 二叉搜索树(BST) 里,中序遍历天然得到有序序列,工程迁移价值很强 很多人第一次写树题不是逻辑不会,而是: 不清楚访问顺序到底是谁先谁后 迭代版不知道什么时候入栈、什么时候出栈 一旦树为空或只有单边链,代码就容易写乱 这题把模板练熟,后面的验证 BST、找第 k 小元素、恢复二叉搜索树等题会更顺。 核心概念 中序遍历:按照 左子树 -> 根节点 -> 右子树 的顺序访问 DFS(深度优先搜索):树遍历最常见的组织方式,中序遍历就是 DFS 的一种访问顺序 显式栈:把递归调用栈手动写出来,用栈保存“回头还要处理的节点” 树高 h:空间复杂度通常写成 O(h),平衡树约为 O(log n),极端退化链表时是 O(n) A — Algorithm(题目与算法) 题目还原 给定二叉树根节点 root,返回它的 中序遍历 结果。 ...

2026年3月6日 · 6 分钟 · map[name:Jeanphilo]

LeetCode 146:LRU 缓存设计(O(1))哈希表 + 双向链表实战

副标题 / 摘要 这题不是“背答案题”,而是缓存系统的基本功:如何在常数时间内同时满足“快速访问”和“按最近最少使用淘汰”。本文从朴素方案推到最优结构,并给出可运行的多语言实现。 预计阅读时长:14~18 分钟 标签:LRU、哈希表、双向链表、系统设计 SEO 关键词:LRU Cache, LeetCode 146, 哈希表, 双向链表, O(1) 元描述:通过哈希表 + 双向链表实现 LRU 缓存,get/put 平均 O(1),附工程场景、常见坑与六语言实现。 目标读者 正在刷 LeetCode 中等题、想吃透“数据结构组合技”的同学 做后端/中间件,需要实现或优化本地缓存的工程师 面试中经常被问到 LRU,但只记住结论、没掌握细节的人 背景 / 动机 缓存是“空间换时间”,但空间是有限的。 当缓存满了,必须淘汰一些键。LRU(Least Recently Used,最近最少使用)假设: 最近被访问的数据,将来更可能再次访问 很久没访问的数据,优先淘汰更合理 工程里常见于: 接口响应缓存 数据库热点记录缓存 页面/会话本地状态缓存 核心概念 LRU 策略:淘汰“最久未使用”的键 访问即更新新鲜度:get 成功后要把该 key 标为“最近使用” 容量约束:put 新 key 造成超容时,需要立即驱逐一个最旧键 O(1) 平均复杂度:get 和 put 都不能线性扫描 A — Algorithm(题目与算法) 题目重述 设计并实现一个满足 LRU 约束的数据结构 LRUCache: LRUCache(int capacity):用正整数容量初始化 int get(int key):若 key 存在返回 value,否则返回 -1 void put(int key, int value): key 已存在:更新 value,并视作最近使用 key 不存在:插入新键值对 若超出容量:淘汰最久未使用的 key 并要求 get 和 put 平均时间复杂度为 O(1)。 ...

2026年2月11日 · 11 分钟 · map[name:Jeanphilo]

LeetCode 138:随机链表的复制(Copy List with Random Pointer)深拷贝全解析

副标题 / 摘要 这道题的难点不是遍历链表,而是正确复制 random 指针所形成的“跨节点引用关系”。本文从朴素思路推导到哈希映射法,讲清为什么它稳定、可维护、易工程落地。 预计阅读时长:12~16 分钟 标签:链表、深拷贝、哈希表、随机指针 SEO 关键词:LeetCode 138, Copy List with Random Pointer, 随机链表复制, 深拷贝, 哈希映射 元描述:用两趟遍历 + 映射表完成随机链表深拷贝,系统讲解正确性、复杂度、工程实践与六语言实现。 目标读者 刷 LeetCode 时对 random 指针题目不够稳的开发者 想厘清“浅拷贝 vs 深拷贝”差异的同学 希望把算法思路迁移到工程对象复制场景的工程师 背景 / 动机 普通链表只要复制 val 和 next,逻辑很直观; 但随机链表多了一个 random 指针,它可能: 指向任意节点(前面、后面、自己) 也可能是 null 这使问题从“线性复制”变成“带额外引用关系的结构复制”。 工程里常见等价问题: 复制工作流节点对象,同时保留跨步骤跳转关系 复制缓存对象图,保持对象间引用一致 复制会话链,保持回溯/快捷索引引用 核心概念 浅拷贝(Shallow Copy):只复制节点壳,内部引用仍指向旧对象 深拷贝(Deep Copy):新建完整对象图,所有引用都指向新对象 节点身份映射:old_node -> new_node,是重建 random 的关键 结构等价:新链表应与旧链表在值与指针关系上同构,但完全不共享节点 A — Algorithm(题目与算法) 题目重述 给定一个长度为 n 的链表,每个节点有: val next random(可指向任意节点或 null) 要求构造该链表的深拷贝并返回新头节点。 新链表中的任何指针都不能指向原链表节点。 ...

2026年2月11日 · 8 分钟 · map[name:Jeanphilo]

LeetCode 19:删除链表的倒数第 N 个结点(双指针一趟扫描)ACERS 全解析

副标题 / 摘要 这题的核心不是“删除节点”,而是“如何在单链表里定位倒数第 N 个节点的前驱”。本文从朴素思路推导到一趟双指针解法,用 ACERS 结构讲透正确性、边界处理与工程迁移。 预计阅读时长:12~15 分钟 适用场景标签:链表基础、双指针、面试高频 SEO 关键词:LeetCode 19, Remove Nth Node From End of List, 删除链表倒数第 N 个结点, 快慢指针, 哨兵节点 元描述(Meta Description):删除链表倒数第 N 个结点的完整 ACERS 解析:从暴力到一趟双指针,含复杂度、常见坑、工程示例与 Python/C/C++/Go/Rust/JS 代码。 目标读者 刚开始刷链表题,想建立稳定解题模板的同学 知道快慢指针,但容易在边界条件上出错的开发者 希望把“题解能力”迁移到工程链式数据处理场景的后端/系统工程师 背景 / 动机 “删除倒数第 N 个节点”是链表题里的经典中档题,常见难点不在删除本身,而在: 单链表不能回退,无法直接从尾部向前数; 可能删除头节点,导致返回值处理复杂; 一旦 next 指针处理失误,容易断链或越界。 掌握它的价值在于: 你会形成一套可复用的“哨兵节点 + 双指针间距控制”模板,这对后续链表题(分组翻转、分割、合并)都很关键。 核心概念 单链表(Singly Linked List):每个节点只有 next 指针,只能向后遍历。 哨兵节点(dummy):在头结点前增加一个虚拟节点,统一“删除头节点”和“删除中间节点”的处理逻辑。 快慢指针固定间距:先让 fast 领先 slow 共 n 步,再同步前进;当 fast 到达末尾时,slow 正好停在目标节点前驱。 A — Algorithm(题目与算法) 题目重述 给你一个链表,删除链表的倒数第 n 个结点,并返回链表的头结点。 ...

2026年2月11日 · 9 分钟 · map[name:Jeanphilo]

LeetCode 2:两数相加(Add Two Numbers)链表进位从朴素到最优解

副标题 / 摘要 这题本质是把「小学竖式加法」搬到链表:同位相加、处理进位、走到末尾后可能还要补一个新节点。文章将从朴素思路推到最优单遍解法,并给出工程场景与多语言实现。 预计阅读时长:12~15 分钟 标签:链表、进位、模拟、LeetCode 2 SEO 关键词:Add Two Numbers, 两数相加, 逆序链表, 进位, LeetCode 2 元描述:用哨兵节点 + 单遍遍历在 O(max(m,n)) 时间完成两条逆序数字链表求和,附常见坑、工程应用和六语言代码。 目标读者 刚开始刷链表题,想建立稳定解题模板的同学 对「进位」和「边界处理」容易写错的中级开发者 希望把算法思维迁移到工程数据流处理的工程师 背景 / 动机 看似只是 LeetCode 入门题,但它练的能力非常实用: 多输入流同步推进(l1、l2 两个指针) 状态跨轮传播(carry 进位) 边界完整性(长度不同、最后一位进位) 这三点在工程里非常常见,例如金额分片累加、多源日志计数合并、流式统计补位等。 核心概念 逆序存储:个位在链表头部,十位在下一节点,以此类推 逐位相加:每轮只处理一个位,值来自 x + y + carry 进位传播:carry = sum // 10,当前位 digit = sum % 10 哨兵节点(dummy):避免首次插入时区分“头节点是否为空” A — Algorithm(题目与算法) 题目重述 给你两个非空链表,表示两个非负整数。 数字按逆序存储,且每个节点存储一位数字。 请将两个数相加,并返回同样逆序存储的结果链表。 题目保证除数字 0 外,这两个数都不会以 0 开头。 输入输出描述 项目 含义 输入 两个链表 l1、l2,每个节点值在 0~9 输出 一个新链表,表示 l1 + l2 的结果(逆序) 示例 1 输入: l1 = [2,4,3], l2 = [5,6,4] 解释: 342 + 465 = 807 输出: [7,0,8] 示例 2 输入: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] 解释: 9999999 + 9999 = 10009998 输出: [8,9,9,9,0,0,0,1] 思路推导:从朴素到最优 朴素思路 1:先转整数再相加 把链表转成整数 n1、n2 做 n1 + n2 再把结果拆位转回链表 问题: ...

2026年2月11日 · 10 分钟 · map[name:Jeanphilo]

Hot100:排序链表(Sort List)链表归并排序 ACERS 解析

副标题 / 摘要 LeetCode 148 的核心不是“会排序”,而是“在链表结构里选对排序算法”。数组可随机访问适合快排/堆排,而单链表最匹配的是归并排序:找中点、递归分治、线性归并。 预计阅读时长:12~16 分钟 标签:Hot100、链表、归并排序、分治 SEO 关键词:Sort List, 排序链表, 链表归并排序, LeetCode 148, Hot100 元描述:用链表归并排序在 O(n log n) 内完成排序,覆盖思路推导、工程迁移、复杂度分析和多语言可运行实现。 目标读者 正在刷 Hot100,想把链表题模板系统化的同学 做链表题经常在“切分和拼接”环节出错的开发者 想搞清楚“为什么链表排序优先用归并”而不是快排的人 背景 / 动机 链表排序在工程里并不罕见: 合并来自多个来源的链式任务队列 对按时间追加的链式日志做离线整理 对内存敏感结构进行“尽量少拷贝”的重排 如果把数组排序思维直接搬过来,往往会遇到: 链表不支持 O(1) 随机访问,分区/堆操作代价高 频繁节点移动容易写出复杂且脆弱的代码 所以这题本质是:为链表选择正确的数据结构友好算法。 核心概念 分治(Divide & Conquer):把链表二分到最小子问题,再向上合并 快慢指针找中点:slow 每次 1 步,fast 每次 2 步 链表归并:两个有序链表线性拼接成一个有序链表 稳定排序:相等元素相对次序可保持 A — Algorithm(题目与算法) 题目还原 给你链表头节点 head,请将其按升序排序并返回排序后的链表。 要求时间复杂度为 O(n log n)。 输入输出 名称 类型 描述 head ListNode 单链表头节点(可能为空) 返回 ListNode 升序排序后的头节点 示例 1 输入: 4 -> 2 -> 1 -> 3 输出: 1 -> 2 -> 3 -> 4 示例 2 输入: -1 -> 5 -> 3 -> 4 -> 0 输出: -1 -> 0 -> 3 -> 4 -> 5 思路推导(从朴素到最优) 朴素做法:转数组再排序 遍历链表把值放到数组 调库排序后重建链表 问题: ...

2026年2月10日 · 6 分钟 · map[name:Jeanphilo]

Hot100:合并K个升序链表(Merge k Sorted Lists)分治归并 O(N log k) ACERS 解析

副标题 / 摘要 这题本质是“k 路归并”。如果直接一条条串行并入,性能会退化;用分治按二叉树方式两两合并,能把复杂度优化到 O(N log k)。本文按 ACERS 模板把思路推导、工程映射和多语言实现一次讲透。 预计阅读时长:12~16 分钟 标签:Hot100、链表、分治、归并 SEO 关键词:Merge k Sorted Lists, 合并K个升序链表, 分治归并, LeetCode 23, O(N log k) 元描述:从串行归并到分治归并,系统讲解 LeetCode 23 的最优复杂度解法与工程实践。 目标读者 正在刷 Hot100,已经掌握 LeetCode 21 的同学 想把“双链表归并”升级为“k 路归并模板”的开发者 在服务端做多路有序流合并(日志、时间线、分片结果)的工程师 背景 / 动机 LeetCode 23 是 LeetCode 21 的自然升级版: 21:2 路归并 23:k 路归并 核心挑战不在“能不能合并”,而在“如何把复杂度控制在可接受范围”。 如果每次把结果链表继续和下一条链表做串行归并,早期节点会被反复遍历,实际性能很容易退化。 核心概念 N:所有链表节点总数 k:链表条数 串行归并:从左到右不断把当前结果和下一条链表合并 分治归并:像归并排序一样,两两合并,按层收敛 最小堆方案:维护 k 个当前头节点,每次弹出最小值并推进其所在链表 A — Algorithm(题目与算法) 题目还原 给你一个链表数组 lists,每个链表都按升序排列。 请将所有链表合并到一个升序链表中,并返回合并后的头节点。 输入输出 名称 类型 描述 lists ListNode[] k 条升序链表,元素可为空 返回 ListNode 合并后的升序链表头节点 示例 1 输入: lists = [[1,4,5],[1,3,4],[2,6]] 输出: [1,1,2,3,4,4,5,6] 示例 2 输入: lists = [] 输出: [] C — Concepts(核心思想) 思路推导:从朴素到最优 朴素法 A:拉平到数组后排序 ...

2026年2月10日 · 9 分钟 · map[name:Jeanphilo]

Hot100:K 个一组翻转链表(Reverse Nodes in k-Group)分组反转 ACERS 解析

副标题 / 摘要 LeetCode 25 是“整链反转(206)”与“区间反转(92)”的组合升级:你要按组切分、组内反转、组间拼接,并正确处理不足 k 的尾组。本文用 ACERS 模板给出工程可复用解法。 预计阅读时长:14~18 分钟 标签:Hot100、链表、分组反转、哑节点 SEO 关键词:Reverse Nodes in k-Group, K 个一组翻转链表, 分组反转, LeetCode 25, Hot100 元描述:K 组链表原地反转模板:分组扫描 + 区间反转 + 安全拼接,含复杂度分析、常见坑与多语言代码。 目标读者 已掌握 206 / 92,希望攻克“多区间连续反转”的 Hot100 学习者 链表题常在边界和拼接步骤出错的中级开发者 需要构建稳定“链表分段处理”模板的工程师 背景 / 动机 在工程里,链式结构的批处理并不少见: 任务链按固定批次重排执行 流水线节点按批回滚或重放 数据清洗链表按批次做原地变换 这类场景的核心诉求是: 组内变换(例如反转) 组间保持顺序 尾部残组按规则保留(不足 k 不反转) LeetCode 25 正是这个能力的典型建模。 核心概念 哑节点(dummy):统一处理头节点参与反转的场景 组前驱(groupPrev):指向当前组前一个节点 组尾探针(kth):从 groupPrev 出发找第 k 个节点,判断是否够一组 组后继(groupNext):当前组反转后要接回的后半链头 组内原地反转:只反转 [groupStart, kth] 区间 A — Algorithm(题目与算法) 题目还原 给你链表头节点 head 和整数 k,每 k 个节点一组进行翻转,返回修改后的链表。 若剩余节点数不足 k,则保持原顺序不变。 要求只能改节点指针,不允许只改节点值。 ...

2026年2月10日 · 8 分钟 · map[name:Jeanphilo]

反转链表 II(Reverse Linked List II)哑节点+头插法 ACERS 解析

副标题 / 摘要 反转链表 II 的关键不在“会反转”,而在“只反转中间一段且不破坏两端连接”。本文用 ACERS 结构讲清哑节点定位、头插法重排与边界处理,给出可复用模板与多语言代码。 预计阅读时长:12~15 分钟 标签:链表、区间反转、哑节点 SEO 关键词:Reverse Linked List II, 反转链表 II, 区间反转, 哑节点, 头插法, LeetCode 92 元描述:单链表区间反转的工程化模板:哑节点 + 头插法,O(n)/O(1),附推导、常见坑与多语言实现。 目标读者 已会 206 反转链表,想进一步掌握“局部反转”的同学 经常在链表题里卡边界(left=1、right=n)的中级开发者 希望把链表指针操作做成稳定模板的工程师 背景 / 动机 Reverse Linked List(206)是“整条反转”,而 92 要求“只反转一个闭区间”。 这类“局部重排”在工程里非常常见: 任务链中的某个分段要逆序重放 事件日志只对一段做回滚重连 数据结构需要在不重建节点的前提下原地调整 难点并非复杂算法,而是: 找准区间前驱与区间首节点 反转过程中不丢失后续链路 区间反转后把前后两端重新接回去 核心概念 哑节点(dummy):统一处理 left = 1 场景,避免头节点特判地狱 前驱指针 prev:最终停在第 left-1 个节点(若 left=1 则停在 dummy) 当前指针 cur:初始为区间首节点 prev.next 头插法(head insertion):每次把 cur 后面的一个节点摘下,插到 prev 后面 A — Algorithm(题目与算法) 题目还原 给你单链表的头节点 head 和两个整数 left、right(1 <= left <= right <= n), 请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。 ...

2026年2月10日 · 7 分钟 · map[name:Jeanphilo]

Hot100:路径和 III 前缀和 + 哈希表统计向下路径(LeetCode 437)ACERS 解析

副标题 / 摘要 “路径不必从根开始、但必须向下”使得这题无法用简单的根到叶 DP 解决。本文用 ACERS 结构讲透 树上前缀和:把任意向下路径转化为“两个前缀和的差”,用哈希表在线计数,做到 O(n) 一次 DFS 统计所有答案。 预计阅读时长:12~15 分钟 标签:Hot100、二叉树、前缀和、DFS、哈希表 SEO 关键词:Path Sum III, 路径和 III, 树上前缀和, 前缀和哈希, LeetCode 437, Hot100 元描述:前缀和 + 哈希表在线统计二叉树向下路径和等于 targetSum 的条数,包含推导、复杂度对比与多语言实现。 目标读者 刷 LeetCode、希望把“树 + 哈希”题型沉淀成模板的学习者 对“路径不从根开始”的树题容易写成 O(n^2) 的同学 做日志调用链 / 层级数据分析,需要在树结构上做区间统计的工程师 背景 / 动机 很多“树上的路径问题”都有一个坑: 你以为要从根出发、或要到叶子结束,但题目允许 从任意节点开始、到任意节点结束(但方向必须向下)。 这意味着: 你不能只维护“从根到当前”的一种状态就完事; 也不能枚举所有起点(那会退化成 O(n^2)); 更不能用滑动窗口(节点值可正可负,窗口单调性不存在)。 这题最值得掌握的点是:把“树上任意向下路径”化为“同一路径上的两个前缀和之差”。 一旦你掌握了这个模型,很多树上统计题都会变成“前缀和 + 哈希表”的熟悉配方。 核心概念 向下路径:只能从父到子(不能回头、不能跨分支) 前缀和(prefix sum):从根到当前节点路径上所有节点值的累加 差分计数:若 curSum - prevSum = target,则 prevSum = curSum - target 路径内哈希表:只统计“当前 DFS 路径上的前缀和”,回溯时必须撤销(否则会把不同分支混在一起) A — Algorithm(题目与算法) 题目还原 给定一个二叉树的根节点 root 和整数 targetSum,求二叉树里 节点值之和等于 targetSum 的向下路径 的数目。 路径不需要从根节点开始,也不需要在叶子节点结束,但路径方向必须向下(只能从父节点到子节点)。 ...

2026年2月2日 · 9 分钟 · map[name:Jeanphilo]