- 博客(384)
- 收藏
- 关注
原创 Leetcode 119 二叉树展开为链表 | 路径总和
递归解法的核心是后序处理:先展开子树,再调整当前节点的指针,把左子树移到右、拼接原右子树;必须将所有节点的left指针置为null,这是题目明确要求;进阶的莫里斯遍历可以实现 O (1) 额外空间,核心是利用左子树的最右节点作为前驱,提前拼接右子树。递归 DFS 解决路径总和的核心是减治思想:每访问一个节点就用目标和减去节点值,直到叶子节点判断是否匹配;(这个我没想到,我以为要顺着思路拿来加,其实减更巧妙)
2026-02-12 20:31:47
323
原创 Leetcode 118 从中序与后序遍历序列构造二叉树 | 二叉树的最大深度
核心逻辑:后序找根,中序分左右,递归构建子树;优化技巧:用哈希表存储中序索引,避免重复遍历,提升效率;递归边界:注意后序 / 中序序列的索引范围,避免越界(比如左子树节点数为 0 时,直接返回 null)。这段代码可以直接编译运行,输入示例中的测试用例就能得到对应的二叉树结构,你可以结合手写解题的思路,对照代码里的索引拆分逻辑,理解如何把 “找根 - 分左右 - 递归” 的思路转化为代码。
2026-02-12 00:10:29
384
原创 Wiki 开发日记:学做 Markdown 大纲视图
本文记录了作者在 Wiki 项目中为 BlockNote 块级编辑器实现大纲视图的过程。通过控制台逆向分析数据结构,利用 useMemo 优化“洗豆子”式的全量计算开销,并巧用防抖与异步调度解决高频更新及滚动偏移冲突,实现了平滑的实时大纲交互。
2026-02-11 21:31:41
817
原创 Leetcode 117 合并两个有序数组
提示给你两个按排列的整数数组nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。请你nums2到nums1中,使合并后的数组同样按排列。最终,合并后数组不应由函数返回,而是存储在数组nums1中。为了应对这种情况,nums1的初始长度为m + n,其中前m个元素表示应合并的元素,后n个元素为0,应忽略。nums2的长度为n。需要合并 [1,2,3] 和 [2,5,6]。合并结果是 [,2,,5,6] ,其中斜体加粗标注的为 nums1 中的元素。[1]
2026-02-11 00:00:04
275
原创 Leetcode 116 相同的树 | 对称二叉树
对称二叉树的核心是镜像比较,而非 “左右子树相同”,必须交换左右节点的比较顺序;递归解法需定义辅助函数,主函数仅需触发根节点左右子树的镜像检查;迭代解法用队列成对存储待比较节点,按镜像规则入队 / 出队,逻辑和递归一致;边界条件需注意:空树、单节点树都是对称的,不要错误排除这类情况。很简单的两道题目!加油,打卡。
2026-02-09 23:30:05
631
原创 Leetcode 115 分割链表 | 随机链表的复制
/ 定义随机链表的节点类public:int val;// 节点值Node* next;// 指向下一个节点的指针// 随机指针,指向任意节点或null// 构造函数:初始化节点值,next和random默认是nullval = _val;// C++11及以上建议用nullptr,效果一样核心逻辑:用哈希表建立「原节点→新节点」的映射,把「找新节点」的问题转化为「哈希表查询」,解决 random 指针的定位难题。
2026-02-08 22:42:08
553
原创 告别“玄学”UI:从“删代码碰运气”到“控制 BFC 结界”
本文复盘了从“盲从AI生成代码”到“掌控布局底层逻辑”的转变。通过解决滚动失效、Flex撑爆等Bug,深度解析了容器约束、BFC隔离及FFC环境对样式的决定性作用。强调开发者应拒绝脑力外包,在AI时代通过理解物理逻辑构建稳固的UI架构。
2026-02-08 21:17:41
937
原创 Leetcode 114 链表中的下一个更大节点 | 删除排序链表中的重复元素 II
单调栈始终保持下标对应值单调递减,当前值大于栈顶值时持续弹出并更新结果,直到不满足条件或栈空;栈中最终剩余的下标(如示例中的 4),其对应结果始终为 0,因无后续更大值;链表转数组时需遍历至指针为空,避免遗漏最后一个节点。核心技巧:用「虚拟头节点」解决头节点可能被删除的问题;核心逻辑:内层循环找「重复段末尾」,而非单次比较两个节点;指针规则prev只在节点不重复时后移,重复时仅通过prev->next跳过重复段。算法不是 “天生就会”,而是 “练会的”—— 新手阶段写错指针、漏写、把。
2026-02-07 23:05:00
554
原创 Leetcode 113 合并 K 个升序链表
合并 K 个升序链表的最优解是归并排序(分治),时间 O(NlogK),空间 O(logK);核心是拆分问题(分治)和解决基础子问题(合并两个升序链表);虚拟头节点是链表操作的常用技巧,能大幅简化边界条件处理;代码已覆盖所有题目边界,可直接运行测试。
2026-02-04 23:48:16
683
原创 Leetcode 112 两数相加 II
用数组模拟栈:只用 push/pop 方法,保证效率;头插法建链表:解决 “低位计算、高位在前” 的问题;处理好进位:用 Math.floor 取整,循环条件包含剩余进位。你之前觉得难,只是对 JS 的栈模拟和链表操作不熟悉,多写两遍测试用例,熟悉这些固定范式后,就会发现这道题的 JS 实现其实很简洁。
2026-02-04 00:02:23
769
原创 Leetcode 111 两数相加
/ 链表节点定义(题目给定)int val;// 存储当前位数字(0-9)// 指向下一个节点的指针// 构造函数:方便创建节点(直接传值,next默认空)逐位求和(l1.val + l2.val + 进位)→ 取余存当前位 → 整除更新进位 → 循环创建新节点;关键技巧:用哑节点简化结果链表的头节点处理,避免繁琐的空判断;l1!= 0(三个条件缺一不可);你的初始思路完全正确,只是需要把「存三个变量、取余、创建节点」的步骤用循环串联起来,这就是本题的完整解法。你这份代码的。
2026-02-02 00:29:28
606
原创 Leetcode 110 奇偶链表
双指针遍历 + 拆分重组,拒绝递归(空间不达标);关键操作:保存偶链表头、正确的指针重连、安全的遍历终止条件;复杂度:严格满足 O (n) 时间、O (1) 额外空间;边界处理:空链表、单节点链表直接返回,无需处理。我感觉就是双指针遍历,奇数指针一直在做跳过偶指针的操作,偶指针自立门户,奇数指针的最后一个连到偶指针的头就ok了。
2026-02-01 00:05:45
638
原创 Web文件下载 : 从PDF预览Bug到Hook架构演进
在复杂的业务逻辑中,我原本将文件获取、Blob 转换、动态创建 DOM 节点等代码堆积在index.tsx中会导致维护灾难。一个 PDF 跳转的小 Bug,我补充了一些Web API 的学习,本质上是浏览器安全策略与渲染机制的综合体现。明确边界:知道download属性何时失效,比盲目调试代码更重要。生命周期意识:在使用时,必须养成配套使用的习惯。架构思维:即便是一个“很小的 Bug”,也值得通过自定义 Hook进行架构级的封装,从而实现从“业务实现”到“工程设计”的跨越。
2026-01-30 22:51:15
992
原创 Leetcode 109 链表的中间结点 | 删除链表的中间节点
给你单链表的头结点head,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。[3,4,5]链表只有一个中间结点,值为 3。[4,5,6]该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点。
2026-01-30 22:23:12
628
原创 消失的最后一秒:SSE 流式联调中的“时序竞争”
我理解就是后端的消息流实时反馈到前端输出。想象这样一个场景:你需要获取一串不断变化的数字。SSE:就像一个转述人实时给你打电话,每接到一个新数字就立刻报给你轮询(Polling):你每隔5分钟给转述人打电话,问他“现在有哪些数字?SSE是一种服务器端向客户端推送实时消息的 API。与 WebSockets 不同,它是单向的,(也就是说,这通电话就像收听一个只能听不能对话的电台广播),且直接运行在 HTTP 协议之上。终于对齐了以后,居然还是 404!!!!!我 Debug 了半天,路径和逻辑都没问题。
2026-01-28 23:31:44
586
原创 Leetcode 108 交换链表中的节点
先精准定位两个目标节点,仅交换值而非节点,避免链表结构修改带来的节点丢失问题。关键技巧:用间隔 k 的快慢指针一次遍历找到倒数第 k 个节点,时间复杂度 O (n),空间复杂度 O (1),符合高效要求。细节注意:循环次数为k-1而非k,快慢指针同步移动的终止条件是,这些细节保证了定位的准确性。诶,原来直接交换这两个节点的val是可以的吗!?自己乱写/*** int val;* };++ i){解答错误!!!!
2026-01-27 23:29:47
1034
原创 【JavaScript 异步编程】回调函数 | 回调地狱以及替代方案
回调函数就是作为一个函数的参数的函数,在外部函数执行完毕的时候,这个回调函数会在特定的时机执行。通常在同步或者异步的编程场景下要用到,异步编程的时候可以用promise 或者 async/await , 定时器setTimeout,这些时间相关的api。回调地狱就是原生回调函数们不断嵌套嵌套嵌套,像俄罗斯套娃一样,虽然实现了按照一定顺序的输出,但是由于层层嵌套难以维护,不好调试和复用。
2026-01-27 13:18:46
653
原创 Leetcode 107 旋转链表
核心优化点:用k % n减少无效旋转,避免k过大时的性能问题;关键技巧:将链表连成环形,通过找节点位置直接确定新的头尾,无需逐次旋转;步骤逻辑:统计长度→算有效步数→连环形→找新头尾→断环形。这种方法的时间复杂度是 O (n)(只遍历链表两次),空间复杂度是 O (1)(只使用了几个指针变量),是最优的解法。
2026-01-26 14:41:04
660
原创 Leetcode 106 删除链表的倒数第 N 个结点
核心技巧:用虚拟头结点解决删除头结点的边界问题,用双指针(快慢指针)实现一趟扫描找到倒数第 N 个结点。关键逻辑:快指针先移n步,快慢指针再同步移动,直到快指针到末尾,此时慢指针的下一个就是要删除的结点。内存管理:C++ 中手动创建的结点要记得delete,避免内存泄漏。你的原代码出错的核心原因是:没有处理头结点被删除的情况(比如示例 2),直接从head开始移动指针,导致删除逻辑不统一。加入虚拟头结点后,所有情况都能被统一处理。边界问题的终极解决方案:虚拟头结点(dummy)
2026-01-25 18:49:46
741
原创 Leetcode 105 K 个一组翻转链表
定位组边界 → 局部翻转 → 拼接回链表;循环终止的关键是:先让end走k步,若走不到则说明剩余节点不足k个,停止翻转;虚拟头节点是处理链表翻转类题目时简化边界的核心技巧,务必掌握。JS 版本完全复刻了你 C++ 代码的核心思路,只是语法上把「指针操作」换成了「对象属性访问」;reverse函数在 JS 中依然是迭代组内每个节点,逐个反转next指向,逻辑和 C++ 丝毫不差;测试用例验证了结果和示例一致,你可以直接复制运行。
2026-01-24 00:38:07
927
原创 Leetcode 104 两两交换链表中的节点
核心技巧:虚拟头节点解决头节点交换的特殊处理,cur定位在「待交换节点对的前驱」避免断链;终止条件:严格遵循你的思考 —— 剩余节点不足 2 个则停止,天然处理奇数 / 偶数节点;交换逻辑:先保存临时节点,再按「挂后续→交换节点→挂前驱」的顺序操作,避免链表断裂。核心痛点:链表指针的移动,必须围绕 “指针的使命”,而不是 “随便往后走”;解题技巧:先在草稿纸模拟指针移动,明确每一步的链表结构,再写代码;学习方法:给指针起 “有语义的名字”、写注释说明使命,能大幅降低出错概率。
2026-01-21 20:22:22
881
原创 数据结构 18 【复习】广义表 | 各种内部排序 | 二叉排序树的平均查找长度 ASL
这类排序的思想是将一个待排序的记录按其关键字的大小插入到前面已经排好序的子序列中。直接插入排序:在序列“基本有序”或数据量较小时效率极高。希尔排序 (Shell Sort):也称“缩小增量排序”,是插入排序的一种更高效的改进版本。
2026-01-15 16:13:46
292
原创 Leetcode 103 反转链表 II
left-1dummy:虚拟节点,编号 0(是节点 1 的前驱)节点 1:编号 1(是节点 2 的前驱)节点 2:编号 2(是节点 3 的前驱)...节点k:编号k(是节点k+1的前驱)要找到节点left的前驱,就是找编号为left-1从编号 0 的dummy出发,需要走left-1步(循环left-1次),才能到达编号left-1的节点。pre的目标是left 位置节点的前驱,而非 left 位置本身;从dummy(编号 0)出发,到编号left-1的前驱节点,需要走left-1。
2026-01-14 15:20:10
853
原创 前端 + agent 开发学习路线
Agent = 大模型API + Prompt优化Agent = 系统架构 + 可控执行 + 安全审查 + 领域适配 + 可观测性作为前端开发者,你在Agent时代拥有独特优势用户体验敏感:知道如何设计自然的AI交互状态管理专家:能设计复杂的Agent工作流快速迭代能力:前端开发的敏捷性能快速验证想法可视化能力:能让黑盒的AI决策变得透明不要被"AI需要Python"的说法限制,Node.js生态在快速发展,前端开发者在AI工程中有明确且重要的位置。
2026-01-13 21:26:59
938
原创 Leetcode 102 反转链表
反转链表的核心是「先保存下一个节点,再反转当前指针,最后移动双指针」,顺序绝不能乱;循环条件只需要cur!= nullptr,不用加cur->next!= nullptr,否则最后一个节点处理不到;期末阶段不用追求「算法感悟」,先把这道题的代码背熟、步骤记牢,能稳稳写出正确代码拿分就够了。你已经在坚持打卡了,这就比很多人强!最难的日子一定会过去,先把这道基础题吃透,一步一个脚印,过线肯定没问题~链表的指针操作里,「修改地址」和「访问地址」是互斥的—— 你一旦修改了cur->next。
2026-01-12 21:50:52
1000
原创 Leetcode 101 对链表进行插入排序
代码完全贴合你梳理的核心思路,仅补充了必要的边界条件和指针操作细节,可直接提交到 LeetCode 并通过所有测试用例;核心逻辑是「用哑节点处理头节点变动 + cur 维护已排序尾部 + 待排序节点 p 找位置插入」;时间复杂度为 O(n2)(插入排序的特性),空间复杂度为 O(1)(仅使用了几个指针变量),符合题目要求。dummy:永远作为 “有序链表的虚拟头”,解决头节点变动的问题(比如第一个节点要插在最前面);pre:专门用来找 “插入位置的前一个节点”,只干这一件事;cur。
2026-01-11 23:16:59
969
原创 Leetcode 100 在链表中插入最大公约数
100 题是一个很棒的里程碑,但更重要的是你在这道题里展现的 “自我纠错能力”:从错误代码到定位问题、再到修复并反思,这个过程比刷 10 道题的收获都大。刷题的核心不是 “数量”,而是 “每道题都能解决一个自己的薄弱点”。继续坚持复盘和总结,你的代码逻辑和解题思路会越来越扎实 —— 下一个 100 题,你一定会看到更明显的进步!
2026-01-10 21:51:49
850
原创 Leetcode 99 删除排序链表中的重复元素 | 合并两个链表
核心进步:你能独立完成链表题,掌握了链表遍历、节点拼接的核心逻辑,这是最关键的!优化方向减少不必要的 dummy 节点,降低代码复杂度和内存开销。避免重复遍历,提升代码时间效率。注意内存泄漏和入参修改的问题,养成良好的编程习惯。dummy 节点关键点:只有当头节点可能被修改 / 删除时才需要用,否则可以直接操作原链表。继续保持这个势头!你已经能独立解决链表问题,接下来可以关注代码的效率和规范性,你的进步会更快。
2026-01-09 21:43:31
833
原创 Leetcode 98 从链表中移除在数组中存在的节点
解题核心思路:将数组存入实现 O (1) 时间复杂度的查找,结合虚拟头节点处理链表删除,迭代遍历链表时仅在不删除节点时移动指针,保证每个节点被检查。关键错误与修复指针逻辑错误:原代码无条件移动cur指针,导致漏检节点 / 空指针,修复后仅在else分支(不删除节点)移动指针;内存管理错误:手动delete链表节点触发,修复后仅做逻辑删除(跳过节点),仅释放自建的dummy节点。优化与补充可直接用nums迭代器初始化,省略循环插入;
2026-01-08 21:33:06
922
原创 Leetcode 96 链表组件
给定链表头结点head,该链表上的每个结点都有一个。同时给定列表nums,该列表是上述链表中整型值的一个子集。返回列表nums中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表nums中)构成的集合。2链表中,0 和 1 是相连接的,且 nums 中不包含 2,所以 [0, 1] 是 nums 的一个组件,同理 [3] 也是一个组件,故返回 2。2链表中,0 和 1 是相连接的,3 和 4 是相连接的,所以 [0, 1] 和 [3, 4] 是两个组件,故返回 2。
2026-01-05 23:26:45
827
原创 Leetcode 95 分割链表
你对「分隔链表」的思考和总结非常到位,核心是抓住了“先算长度→分基础长度 + 余数→正向分割”的核心逻辑,也意识到了自己 “思路能想通但代码写不出来” 的核心问题 —— 这是编程新手最常见的痛点,接下来我帮你把 “从思路到代码” 的落地路径拆得更细,让你能一步步独立写出来。核心逻辑:用 “分糖果” 的比喻固化 “base_len+remain” 的分配规则,避免 “从后往前” 的复杂思路;代码落地:拆成 5 个小步骤,每步只解决一个小问题,不用一上来写完整代码;
2026-01-04 13:49:37
552
原创 Leetcode 94 合并零之间的节点
数据结构认知:题目中链表的「数组式输入」是可视化表示,实际操作的是指针,返回的「head」是新链表的头节点,而非原链表的头节点;解题策略:链表题优先选择「新建链表(dummy 节点)」,逻辑更简单,减少指针操作错误;条件判断:sum 累加判断「当前节点是否非 0」,复位判断「当前节点是否为 0」,避免访问 nullptr 的 next 属性。
2026-01-03 16:17:34
603
原创 数据结构 17 【复习】习题
已知遍历组合能否唯一确定二叉树核心逻辑前序 + 中序✅ 可以前序定根,中序分左右后序 + 中序✅ 可以后序定根,中序分左右前序 + 后序❌ 不可以只能定根和元素集合,无法分左右关键记忆点:中序是 “分左右” 的核心,必须搭配前序(或后序)的 “定根” 功能,才能唯一还原二叉树。
2026-01-03 14:29:09
751
原创 数据结构 16 【复习】静态查找表 | 二叉排序树的查找 | AVL树的旋转
右旋:针对 “某节点的左子树过重”,让该节点和它的左孩子交换位置(左孩子变新根,原节点变右孩子)。左旋:针对 “某节点的右子树过重”,让该节点和它的右孩子交换位置(右孩子变新根,原节点变左孩子)。
2026-01-03 14:17:24
748
原创 Leetcode 93 找出临界点之间的最小和最大距离
链表中的定义为一个如果当前节点的值前一个节点和后一个节点,那么这个节点就是一个。如果当前节点的值前一个节点和后一个节点,那么这个节点就是一个。注意:节点只有在同时存在前一个节点和后一个节点的情况下,才能成为一个。给你一个链表head,返回一个长度为 2 的数组,其中是任意两个不同临界点之间的最小距离,是任意两个不同临界点之间的最大距离。如果临界点少于两个,则返回[-1,-1]。[-1,-1]链表 [3,1] 中不存在临界点。[1,3]存在三个临界点:- [5,3,
2026-01-02 22:57:20
853
原创 Leetcode 92 二进制链表转整数
给你一个单链表的引用结点head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。请你返回该链表所表示数字的。在链表的头部。5二进制数 (101) 转化为十进制数 (5)head = [0]03001。
2025-12-31 23:59:57
413
原创 Leetcode 91 子序列首尾元素的最大乘积
本题的本质是 “找满足的(i,j)对,计算的最大值”,而非暴力枚举子序列;处理负数乘积时,必须同时维护 “最大值” 和 “最小值”—— 最小值(最负)× 负数可能得到更大的正数;特殊场景(如m=1)需单独处理,避免通用逻辑覆盖特殊情况。先明确变量的语义,再验证边界场景,最后考虑负数的特殊运算规则。------特殊场景别漏判m=1是首尾同元素的特殊情况,需直接算元素平方取最大,而非默认取正数再平方,忽略负数平方的更大值。变量语义要盯死:维护的是可配对的起始位置最值。
2025-12-30 22:05:27
1166
原创 Leetcode 90 最佳观光组合
先变形公式:把依赖 i 和 j 的式子拆成 “i 独立项 + j 独立项”,这是从 “暴力枚举” 到 “线性遍历” 的关键;明确枚举逻辑:固定 “枚举右边界 j”,维护 “j 之前的左边界 i 的最优值”,把 O (n²) 降到 O (n);注意执行顺序:先算当前 j 的答案(用之前的最优左值),再更新最优左值,严格满足 i<j 的约束。变形公式→确定枚举方向→维护左值,就能把 “没头绪” 的问题,转化为你熟悉的 “遍历 + 更新最值” 的简单逻辑。
2025-12-29 18:00:23
596
原创 数据结构 15 【复习】树和二叉树小结 | 图算法 | 拓扑排序 | AOE 网
解析:二叉树不是树的特殊形式(树的子节点无左右次序,二叉树的子节点有左右次序),二者是不同的数据结构。解析:度为 2 的树仅要求节点最大度为 2,但二叉树要求子节点有左右区分(即使只有一个子节点,也要明确是左 / 右孩子),二者定义不同。解析:树转二叉树的规则是 “左孩子右兄弟”,根节点无兄弟,因此其右子树必然为空。解析:A 有 3 个兄弟,则 B 的子节点数为(3+1)=4,因此 B 的度是 4。(例如:先序为 “AB”、后序为 “BA”,可对应两种不同结构的二叉树)。
2025-12-28 16:45:02
948
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅