2023-07-05 14:17:49
《labuladong的算法小抄》强调以量化目标为导向,通过框架思维系统学习算法,重点在于明确目标、聚焦核心操作,并优先通过二叉树问题培养递归与分治思维。以下是具体内容梳理:
一、学习算法的目标管理方法论量化目标的重要性
无法量化的目标(如“学好算法”)缺乏可操作性,需拆解为具体指标。例如将“进大厂”拆解为“半年刷300道题”,进一步细化为“每日固定时段刷题2-3道”,并通过每日复盘调整进度。
核心逻辑:采用计算机递归思维,自顶向下逐步求精,反向推导执行路径。
聚焦核心目标,避免精力分散
以英语阅读为例,若目标为“完成题目”,则无需纠结所有生词;同理,学习算法时需区分主次(如优先掌握框架而非细节实现)。
关键原则:将有限精力投入关键路径,通过“二八法则”加速目标达成。
数据结构的存储方式
数组:顺序存储,通过下标直接访问元素,适合静态数据场景。
链表:链式存储,通过指针动态连接节点,适合频繁插入/删除的场景。
本质区别:数组依赖连续内存,链表通过指针解耦物理存储与逻辑顺序。
数据结构的基本操作框架
通用操作:增删查改,所有数据结构均围绕这四类操作设计。
遍历框架:
数组:线性迭代,通过for循环依次访问每个元素。
void traverse(int[] arr) { for (int i = 0; i < arr.length; i++) { // 访问 arr[i] }}链表:支持迭代与递归两种方式。迭代通过指针移动遍历,递归则隐式利用调用栈。
// 迭代遍历void traverse(ListNode head) { for (ListNode p = head; p != null; p = p.next) { // 访问 p.val }}// 递归遍历void traverse(ListNode head) { if (head == null) return; // 访问 head.val traverse(head.next);}二叉树:非线性递归遍历,分为前序、中序、后序三种方式,核心逻辑为“左子树→右子树”的递归分解。
void traverse(TreeNode root) { if (root == null) return; traverse(root.left); // 访问左子树 traverse(root.right); // 访问右子树 // 中序遍历需在此处访问 root.val}优先刷二叉树问题的原因
框架思维培养:二叉树的递归遍历模式(分解子问题)可直接迁移至回溯、动态规划等算法。
技巧覆盖广泛:如分治思想(左右子树独立处理)、递归状态管理(调用栈隐式存储中间结果)等。
刷题路径建议
阶段一:集中攻克树类问题(如二叉树遍历、层次遍历、最近公共祖先等),掌握递归与分治框架。
阶段二:拓展至回溯(决策树)、动态规划(多阶段决策树)、分治(递归分解问题)等专题,利用树结构思维降低理解难度。
示例:动态规划中的“爬楼梯”问题可视为树的前序遍历,回溯算法中的“全排列”问题本质是决策树的深度优先搜索。
每日固定时段刷题,屏蔽干扰以保持专注。
复盘时记录未达标原因(如框架应用不熟练、边界条件遗漏),针对性弥补。
扩展至其他数据结构时,对比其与树的异同(如图可视为多叉树的扩展),强化框架迁移能力。