- 博客(13)
- 收藏
- 关注
原创 [从零开始面试算法] (12/100) LeetCode 121. 买卖股票:一次遍历的“后悔药”
本文介绍了如何用一次遍历法解决LeetCode121股票买卖问题。通过维护"历史最低价"和"最大利润"两个变量,在遍历过程中动态计算当天卖出能获得的最大利润,并更新历史最低价。这种方法的时间复杂度为O(n),空间复杂度为O(1),是这个问题的最优解。关键技巧在于先计算利润再更新最低价,确保符合"先买后卖"的规则。
2025-09-06 20:00:00
1169
原创 [从零开始面试算法] (11/100) LeetCode 226. 反转二叉树:递归的“镜像”魔法
本文通过LeetCode 226题"反转二叉树"讲解了递归在树结构问题中的应用。作者从初始思考出发,逐步完善递归方案:首先确定终止条件为节点为空,然后采用前序遍历顺序,先交换当前节点的左右子节点,再递归处理左右子树。文章用"将军下令"的比喻形象地描述了递归过程,并提供了C++实现代码,分析了时间复杂度和空间复杂度。核心思想是将大问题分解为处理当前节点、递归处理左右子树三个步骤,强调理解递归函数调用的本质和对递归的"信任"是掌握这类问题的关键。
2025-09-04 23:14:45
1454
原创 [从零开始面试算法] (10/100) LeetCode 155. 最小栈:辅助栈的“历史快照”思想
本文探讨了如何设计一个支持O(1)时间获取最小值的特殊栈结构。通过分析仅用变量记录最小值的缺陷,指出其在pop操作时会丢失历史信息。进而提出使用辅助栈的解决方案,使辅助栈的每个元素同步记录主栈对应状态的最小值。这种"历史快照"机制保证了所有操作(push/pop/top/getMin)都能在O(1)时间内完成,典型体现了"空间换时间"的思想。文章详细解释了辅助栈与主栈的同步维护原理,并提供了C++实现代码,强调哨兵技巧在简化边界处理中的重要作用。
2025-09-03 23:35:26
1414
原创 [从零开始面试算法] (09/100) LeetCode 21. 合并两个有序链表:迭代与递归的优雅
本文介绍了合并两个有序链表的两种经典方法。迭代法通过虚拟头节点(dummy node)简化边界处理,使用指针遍历比较并链接节点,空间效率高(O(1))。递归法则以更简洁的代码实现,通过比较头节点并递归处理剩余部分,但需要额外栈空间(O(m+n))。两种方法时间复杂度均为O(m+n),迭代法适合处理长链表,递归法则更体现分治思想。理解这两种方法能帮助开发者根据场景选择合适解法,并深入掌握链表操作技巧。
2025-09-02 23:02:11
1329
原创 [从零开始面试算法] (08/100) LeetCode 169. 多数元素:哈希与摩尔投票的对决
本文介绍了求解数组中多数元素的两种方法:哈希表法和摩尔投票法。哈希表法通过统计元素频率实现,时间复杂度O(n),空间复杂度O(n),思路直观但需要额外存储。摩尔投票法采用"擂主对决"机制,同样时间复杂度O(n)但空间复杂度优化至O(1),通过元素间相互抵消最终确定多数元素,虽思路巧妙但代码简洁。两种方法各具优势,哈希表通用性强,摩尔投票空间效率极佳,开发者可根据具体场景选择合适解法。
2025-09-02 23:00:08
853
原创 [从零开始面试算法] (07/100) LeetCode 70. 爬楼梯:你的第一道动态规划入门题
本文介绍了动态规划思想在解决爬楼梯问题中的应用。通过分析到达第n阶楼梯的最后一步可能来自第n-1或n-2阶,推导出递推公式f(n)=f(n-1)+f(n-2)。文章对比了纯递归解法(存在重复计算)和动态规划解法(使用备忘录避免重复计算),并给出了空间优化的O(1)解法。最终总结出:动态规划通过自底向上填表和状态压缩,能有效将指数级复杂度优化为线性复杂度。
2025-08-26 23:58:46
1416
原创 [从零开始面试算法] (06/100) LeetCode 104. 二叉树的最大深度:递归的“分解”艺术
对于一个每层都铺满的“完美”二叉树(满二叉树),其节点数和深度的关系是明确的。:求解树的高度/深度问题的核心公式是 1 + max(左子树高度, 右子树高度)。当递归到空节点时(比如一个叶子节点的子节点),我们知道空树的深度为 0,直接返回。maxDepth(15) 和 maxDepth(7) 都是叶子节点,它们的深度计算出来也都是 1。我们可以利用这个特性,将一个“求整棵树的深度”的大问题,分解成“求其子树深度”的小问题。代入第一步的公式:maxDepth(3) = 1 + max(1, 2) = 3。
2025-08-26 23:56:22
689
原创 [从零开始面试算法] (05/100) LeetCode 20. 有效的括号:栈的经典演绎
如果栈中还有剩余的左括号,说明它们没有被闭合(例如 "([{"),st.empty() 返回 false,这正是我们想要的结果。那么,我的思路是:用两个指针,一个指向头,一个指向尾。如果匹配,就让两个指针向内收缩,继续判断次外层的。有效的括号,比如 "{[]}",具有一种对称性,最外层的 { 和 } 对应,内层的 [ 和 ] 对应。这个“层层向内”的思路,对于 "{[]}" 这种完全对称的例子是有效的。给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
2025-08-25 23:59:58
748
原创 [从零开始面试算法] (04/100) LeetCode 206. 反转链表:迭代与递归的双重奏
当前珍珠” curr 已经成功穿到了新绳子上,所以它现在变成了新绳子的头,prev 需要更新为 curr 的位置。它的核心思想是:从头到尾遍历原始链表,在遍历的过程中,逐个地将每个节点的 next 指针“反向”。当 head 为空,或者 head->next 为空(即链表为空或只有一个节点)时,反转它本身就是它自己,直接返回 head 即可。“新绳子” prev 为空,“当前珍珠” curr 为原始链表的头。将当前珍珠的 next 指针,从指向原始的下一个节点,改为指向“新绳子”的头部。
2025-08-23 23:58:11
799
原创 [从零开始面试算法] (04/100) LeetCode 136. 只出现一次的数字:哈希表与位运算的巅峰对决
在每一次循环中,我们将累加器的当前值与数组中的当前元素 num 进行异或运算,并将结果存回累加器。这道题是面试中的高频题,因为它像一个十字路口,既可以通往我们熟悉的数据结构之路(哈希表),又可以引领我们进入一个全新的、充满数学之美的领域——而哈希表解法中,如果数组有 1000 万个元素,哈希表也需要存储约 500 万个元素,内存占用随 n 线性增长,所以是 O(n) 空间。当循环结束时,所有成对出现的数字都已相互抵消(变成了 0),累加器中剩下的就是那个唯一的、只出现了一次的数字。这就是典型的 O(n)。
2025-08-21 23:58:43
812
原创 [从零开始面试算法] (03/100) LeetCode 448. 消失的数字:原地哈希的极致空间优化
本文介绍了原地哈希算法,通过将数组本身作为哈希表来优化空间复杂度。以LeetCode 448题为例,常规解法使用哈希表导致O(n)空间复杂度。原地哈希的巧妙之处在于利用数组索引和值的对应关系,通过改变元素符号来标记数字是否存在。算法分为两个阶段:遍历数组标记出现过的数字,再检查未被标记的索引找出缺失数字。这种方法在O(n)时间复杂度和O(1)空间复杂度内解决问题,适用于元素值在特定范围内的数组操作。
2025-08-19 23:21:15
1076
原创 [从零开始面试算法] (02/100) LeetCode 283. 移动零:快慢指针的艺术标题】
本文以LeetCode283题"移动零"为例,介绍了双指针算法中的快慢指针模型。首先分析了O(n²)暴力解法的不足,然后通过"清理房间"的比喻生动阐释了快慢指针的工作原理:fast指针遍历数组寻找非零元素,slow指针负责将非零元素按顺序排列。文章对比了"填充0"和"交换"两种优化方案,指出前者在大多数情况下性能更优。最后解答了关于指针本质和动态规划区别的常见问题,总结了快慢指针在解决原地分区问题中的优势,时间复杂度优化至O(n
2025-08-19 23:07:05
976
原创 [从零开始面试算法] (01/100) LeetCode 1. 两数之和:哈希表的亲密接触
摘要:本文通过LeetCode"两数之和"问题,详细解析了暴力解法与哈希表优化方案。作者首先展示时间复杂度O(n²)的双重循环暴力解法,随后引入哈希表(unordered_map)概念,通过"智能储物柜"的生动比喻解释了哈希函数的运作原理。最终给出C++最优解代码,利用哈希表将时间复杂度降至O(n),实现"空间换时间"的优化策略。文章不仅提供完整代码实现,还深入浅出地讲解了哈希表的核心机制和碰撞处理方法,适合算法初学者理解数据结构优化思路。
2025-08-17 13:23:52
1230
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人