
学习日记day56。不是新框架的发布记录也不是什么热门技术的测评这是我个人学习记录里的一个普通节点。连续记录了56天每天留出固定时间老老实实学一点自己真正需要补的东西。第56天不巧赶上一个阶段节点我停下来做了一次完整复盘把前面积累的“我好像会了”重新验证了一遍结果发现不少地方其实只是“我看过”。这篇日记就是记录这次复盘和验证的过程包括我怎么重新调整学习路线、怎么用输出倒逼输入、以及当天亲手写完代码后发现的三类典型问题。如果你也在自学路上学到中途开始自我怀疑这篇内容应该能给你一些具体可用的参考。1. 为什么在第56天我停下来重新设计学习路线1.1 持续56天后的真实阶段复盘不是没学是白学了先交代一下背景。前55天里我名义上有43天完成了学习任务真正中断的天数是12天。表面看这个完成率不算差但第56天我做了个事把前几周记的笔记翻出来随机挑了几个核心概念尝试不看资料复述。结果是相当一部分概念我只能说出“好像跟内存有关”“大概是用来解决某个问题的”但说不出完整逻辑。这个结果让我有点警觉。看起来我每天确实坐在书桌前学了但学的方式是看视频、划重点、抄笔记。这种模式的问题在于输入很轻松大脑几乎不费力而真正需要用的时候需要的是主动回忆和组织表达这部分能力几乎没练到。说白了我的学习停留在“认字”阶段没有进入“会用”阶段。第56天这篇文章本质上就是针对这个问题做的一次纠偏记录。很多自学者都会经历类似阶段时间花了、笔记厚了、进度表上也满了但合上资料和自我测试时却发现漏洞百出。不是你不够努力是你的学习方式太依赖“输入”缺少“提取”。那就必须调整路线。1.2 学习路线的三段式调整输入、内化、输出我原来的学习流程可以概括成一条直线找资料、看讲解、收藏完事。回想起来收藏夹里躺着大量“以后肯定有用”的内容实际上再也没有打开过。这就是典型的“囤积心态”以为收藏等于学会。第56天开始我把流程重构成三段并把每一段都分配了固定时间。整个学习时间按1.5小时算的话输入控制在40分钟内化控制在20分钟输出控制在30分钟。输入阶段只负责看书、看文档、看课程视频这时候允许“看不懂也没关系”先建立整体印象。内化阶段关上资料用自己的话把刚学的东西讲一遍。可以自言自语也可以写在纸上。关键是“不看着原文表达”这一步就是主动回忆。输出阶段把概念变成实际产物。学编程就写代码学知识就写总结性文章学工具就动手配置环境。输出不需要精致但必须真实运行或真实使用。这个调整背后的逻辑不复杂。记忆研究者很早就发现被动阅读之后24小时人能记住的内容往往不到三成但如果学完后主动复述和应用留存率能大幅提高。原因在于主动回忆每一次都是在给大脑信号“这个信息很重要”于是大脑才会把它往长期记忆里搬。所以不要再问“为什么学了就忘”先问自己“学完后有没有主动提取过”。1.3 目标管理的三个实际做法拆小、减量、写反思除了改变学习方式我还重新设计了目标管理方式。前55天定目标时我走的是“宏大路线”比如“本月掌握算法基础”这种目标的问题是没有可执行性结果就是今天学数组明天跳链表最后什么都没有沉淀。现在改用三个做法把大目标拆成一周颗粒度的小任务。不再说“学会数据结构”而是说“这周能手写单链表的增删查改”。每天设定最小行动。哪怕再忙、状态再差也保证做满20分钟。这20分钟可以只完成输入环节但绝不能断档。连续性本身比单次时长更重要。睡前写反思三句话。第一句是“今天学到了什么”第二句是“哪里卡住了”第三句是“明天准备做什么”。三句话加起来不会超过五分钟但它把每天的学习变成一件有始有终的事不容易稀里糊涂过日子。这三点看起来平淡实际效果却很明显。拆小目标解决了“不知道学啥”的问题最小行动解决了“今天太忙不想学”的问题睡前反思解决了“学完就忘”的问题——因为它逼着你在当天晚上做了一次主动回忆。2. 第56天的核心学习内容用费曼输出法吃透数组与链表2.1 为什么第56天选择数组和链表作为补强对象前55天里我其实是“学过”数组和链表的但第56天复盘时发现自己连“数组为什么访问快”都讲不严谨只能说“好像是连续内存”。这种理解水平显然不合格所以我把它们当作第一个补强对象。选择它们还有一个原因数组和链表是几乎所有复杂数据结构的基础。栈、队列、哈希表的底层设计思路都可以往这两个东西上靠。把这个基础夯实后面学别的会顺畅很多。为了把概念吃透我没有再看一遍视频而是换了一种方法——自己给自己讲。按照费曼学习法的思路如果一个概念不能用大白话讲给完全没基础的人听那大概率没有真正理解。于是我试着用生活场景类比数组就是电影院的一排固定座位。座位号就是下标知道座号直接走过去所以访问任意一个座位都很快但如果要往中间加一个人那后面所有人都得往旁边挪一个位置。链表则像是寻宝游戏里的一串线索卡片每张卡片上写着“下一个线索在一棵树下面”。你想找第5张卡片必须从第一张开始一张张往后翻因为每张卡片只记录了下一张的位置但好处是往中间插入一张新卡片时只需要改变前后两张卡片的指向其他卡片根本不用动。这个类比虽然粗糙但把“连续内存随机访问快”和“分散节点通过指针连接”这两个核心区别讲清楚了。第56天的第一项输出就是给这个类比配了文字版的内存示意图。2.2 今天的学习日记是怎么记的结构、图示、自问自答第56天的日记我没有像以前那样大段摘抄资料而是按照固定结构来写。整篇日记分六块一句话定义今天学的概念是什么必须控制在两行以内。内存模型描述用文字画出数据在内存里的存储方式。核心操作拆解访问、插入、删除分别怎么执行。复杂度速查表用表格记录增删查改的时间复杂度。自问自答至少写三个自己问自己的问题并写出答案。手写代码把今天学的核心算法完整实现一遍。自问自答这一块我觉得价值最高。比如我给自己提问“为什么链表头部插入是O(1)但要插入到指定位置却是O(n)”这个问题迫使我去思考定位与插入是两个步骤。答案梳理下来就是头部插入不需要查找位置直接改新节点的next指向原头节点即可指定位置插入则必须从头开始遍历去寻找前驱节点遍历的过程就是O(n)真正执行插入只是O(1)。想通了这一点后面看各种链表的优化技巧就不再发怵。2.3 今天亲手实现的代码单链表插入与反转只讲概念不写代码早晚会眼高手低。第56天我选了两个最基础但最容易出错的操作用代码落实头部插入和反转链表。用Python实现单链表节点非常简洁class ListNode: def __init__(self, val0, nextNone): self.val val self.next next def insert_at_head(head, val): 将新节点插入链表头部返回新的头节点。 new_node ListNode(val, head) return new_node def reverse_list(head): 反转单链表返回反转后的头节点。 prev None current head while current: next_node current.next # 先保存下一个节点 current.next prev # 把当前节点的指针指向前一个节点 prev current # prev 移到当前节点 current next_node # current 移到下一个节点 return prev这段代码核心只有while循环里的四行但初学时会觉得每一行都在“转圈”。我用一个具体例子跑了一遍逻辑假设链表是1 - 2 - 3head指向1。初始状态prev是Nonecurrent指向1。第一轮循环保存next_node为2把1的next指向None然后prev变成1current变成2。第二轮循环保存next_node为3把2的next指向1然后prev变成2current变成3。第三轮循环保存next_node为None把3的next指向2然后prev变成3current变成None。循环结束返回prev也就是3。注意这里有一个很多新手容易踩的坑如果在把current.next改成prev之前不先保存next_node链表的原始链接就断了后面的节点全部丢失。所以那行next_node current.next看起来不起眼实际上是最关键的一步。3. 实操过程记录手写代码、运行结果与性能对比3.1 手写链表时的现场记录与思路追踪第56天实操环节我刻意要求自己不打开任何参考代码纯凭记忆写。整个过程大概花了40分钟我把现场情况记录一下。前十分钟在写ListNode类这个比较简单一次通过。接下来写insert_at_head时我一开始没想清楚要不要返回新头节点。直接写了一个不返回的函数后来一运行发现链表完全没变化才意识到在头部插入时整个链表的入口已经变了如果不把新节点返回给调用者外部永远拿不到新的链表。这个问题看似细微但在真实的工程代码里很容易漏。反转链表花的时间最长。我第一次写的时候把循环条件写成了while current.next结果链表一为空的边界情况直接就崩了。后来重新检查才改成while current保证空链表也能走入函数并自然返回None。还有一个现场细节我尝试不看资料纯文字追踪指针变化绕了大概三分钟才理顺。最后还是在纸上画了三行箭头才彻底明白。所以如果只看代码觉得晕建议你也拿张纸把prev、current、next_node三个变量每次循环后的值都写出来比盯着屏幕效率高得多。3.2 数组与链表的性能对比速查表手写代码之后我把数组和链表的核心操作复杂度整理成一份速查表这样可以随时查阅也方便后续学数据库索引、Redis底层结构时做对照。操作数组时间复杂度链表时间复杂度关键说明按下标/值访问O(1)O(n)数组是连续内存可直接计算地址链表需要从头遍历头部插入O(n)O(1)数组需要整体后移链表只需修改新节点与头节点指针尾部插入O(1) 摊还O(n)数组扩容后可直接写末尾普通链表需要遍历到最后一个节点中间插入O(n)O(n)数组要移动元素链表要遍历定位定位后插入本身是O(1)删除指定元素O(n)O(n)数组要移动元素链表要找到前驱节点才能断开衔接内存占用低且连续每个节点额外存指针链表每个节点有额外开销且节点分散把这张表打印出来贴在桌前用处很大。很多时候面试题讨论“为什么业务代码里数组更常用”答案其实都能从这张表里推导出来数组在访问和尾部插入上表现极好而链表最大的优势只在头部插入和频繁中间增删的场景前提还得是你能快速拿到插入位置。3.3 今天踩到的三个坑边界、指针、贪多实操的时候我踩了三个跟之前完全一样的坑记录一下免得以后再犯。第一个坑是只在常规场景测试。我写了插入和反转后随手用一个五节点的链表跑了一遍看着输出正确就觉得完事了。后来多问了自己一句“边界是什么”才意识到空链表、单节点链表、两个节点链表都没有测过。补测之后发现空链表反转返回的应该是None单节点反转返回的应该是自己。这些逻辑在循环里其实是自然满足的但不亲手测一遍心里始终没底。第二个坑是关于指针的。用调试器单步跟踪反转链表时变量列表里三个指针跳来跳去我看了半天还是很晕。为什么因为调试器只告诉我“现在指向谁”没告诉我“为什么指向他”。解决办法是关掉调试器拿笔在纸上画。经过三轮手画我真正理解了“每次循环只反转一个箭头”的本质。学习这类带指针的算法时纸笔永远是第一工具演示动画和调试器都只是辅助。第三个坑是贪多。原计划第56天想顺手把栈、队列也复习了结果刚碰了一个小时就发现贪多嚼不烂。反转链表写到一半栈的笔记还摊在旁边两边都没学好。后来果断把栈和队列往后推规定当天只解决一个核心问题。这个教训很直接一次一个核心概念学透再走下一个比同时开三四个战场有效得多。4. 常见问题与排查技巧实录学了就忘、动手就废、时间不够4.1 学了就忘怎么办间隔重复与主动回忆这是我后台收到私信最多的一类问题也是我自己前55天的核心痛点。先说结论学了就忘很正常遗忘本来就是大脑节省能量的默认机制但我们可以用两个策略跟它对抗。第一个策略是间隔重复。学完一个概念之后第一次复习安排在当天晚上第二次安排在第二天第三次安排在三天后第四次安排在一周后。每次复习不需要太久五到十分钟即可。这看起来没什么稀奇但它可以把一个信息从“短期缓存”一点点推入“长期存储”。第二个策略是主动回忆。这里的动作不是“再读一遍”而是“试着默写或复述”。给自己一张白纸写下能想起来的一切然后再打开笔记对照。凡是能写出来的部分才是真正属于你的知识写不出来的部分就是需要重新看的地方。我第56天把“数组为什么访问快”这个问题复述给一张白纸时第一次只能写出“连续内存”四个字这个缺口很诚实也直接引发了我当天上午的补课。4.2 代码看懂了但写不出来怎么办先抄再默最后变如果只看视频、看文档都能看懂但当合上资料要自己写时却一片空白这个问题几乎人人都会遇到。我的应对方法是“三级训练法”。第一级叫照抄。照着参考代码一行一行打出来这个阶段不要求记忆只要求手指熟悉语法结构。第二级叫默写。把参考代码拿掉只留一个题目描述凭记忆把代码写出来。写不出来就回去看一眼再合上继续写直到能完整默写为止。第三级叫变形。在默写的基础上改需求比如把反转整个链表改成反转前三个节点或把插入头部改成按位置插入。这个阶段要求真正理解代码逻辑才能做灵活修改。以反转链表为例我照抄用了5分钟默写用了15分钟变形花了20分钟。当我能顺利实现“反转从第2个节点到第4个节点”的新函数时才算真正跟反转链表“混熟”。这个训练法的关键不在数量而在每一级都必须动脑默写逼你回忆结构变形逼你理解语义。4.3 时间不够用怎么保持每日投入三档时间策略“每天真的很忙怎么坚持下来”这也是高频问题。我给自己的方案是准备三档时间按当天的实际情况切换。完整档约90分钟。安排“输入 内化 输出”全程周末或工作不忙的日子使用。碎片档约20分钟。只做两件事快速回顾昨天的日记 做一道题或写一个小函数。最低档约10分钟。只做一件事把前一天的笔记重新看一遍然后在日记里写一句“今天只能看这么多了”。这个策略的关键在于“不断档”。学习最怕的不是一天没学而是断档三天后彻底放弃。哪怕每天只有10分钟的接触也能让大脑保持对这个领域的敏感性后续再投入完整一小时时不需要额外花时间“进入状态”。我个人实测下来三档切换的坚持成本很低。最低档其实没有任何学习压力它最大的作用是维持“我还在做这件事”的自我认同这种认同感在长期自学里比任何方法论都重要。4.4 我的学习日记模板直接抄作业最后分享一个可以直接复制的学习日记模板。这就是我第56天使用的结构Markdown格式任何笔记软件都支持。建议你也按这个结构记录不要在意排版是否好看先把结构固定下来。# 学习日记 day56 日期2025-XX-XX 主题单链表的插入与反转 1. 今天在学什么 数组与链表的区别、单链表头部插入、反转链表 2. 今天想解决什么问题 为什么链表头部插入是 O(1) 但按位置插入是 O(n) 反转链表时为什么要先保存 next 节点 3. 用自己的话解释核心概念 数组是连续内存像一排固定座位链表是分散节点靠指针连接像寻宝线索。 头部插入时直接改指针就是 O(1)按位置插入要先遍历找到前驱节点所以是 O(n)。 4. 代码或笔记摘录 贴入当天手写并通过运行的代码 5. 遇到卡点 反转链表时忘记保存 next 节点导致链表断裂。 解决在修改 current.next 之前先保存 next_node。 6. 明天计划 学习基于链表的 LRU 缓存实现思路。这个模板里最有价值的字段是“遇到卡点”。因为它逼着你承认今天哪里卡住了而不是假装一切顺利。解决卡点的过程才是真正成长发生的过程。我前55天没写这一栏笔记里全是顺利的复述第56天开始补上感觉整篇日记的含金量立刻不一样了。最后再聊一句真心话。写学习日记看起来只是增加了一个额外环节但它其实是把“学没学”变成“学没学会”的分水岭。哪怕你完全不用我的模板只要每天睡前认真回答一次“今天到底解决了什么问题”整个学习状态就会发生明显变化。第56天没有让我突然变强但它让我看清了前面55天的问题所在这本身就是巨大的收获。下一个56天我也建议你从今天开始记档。