【Java实习面试算法冲刺】链表

📅 2026/7/7 1:32:03
【Java实习面试算法冲刺】链表
第4类题型链表为什么链表题你感觉思路不难一写代码却总把链断掉很多同学刷链表题时第一反应都是“这题思想不难就是操作麻烦”。这句话只说对了一半。链表题真正拉开差距的地方不是你知不知道反转、删除、判环这些套路而是你能不能在每一步指针修改时都保持清醒。这类题最容易暴露出几种典型问题你知道要改next但一改就把后续节点丢了。你会写删除节点却没提前想到头结点可能变化。你记住了快慢指针模板但说不清为什么这样走一定能找到答案。1. 核心知识点链表题的难点通常不是算法思想多复杂而是指针操作顺序很容易错。你必须先养成两个习惯改指针之前先保存next。遇到头结点可能变化的问题优先考虑虚拟头结点dummy。链表高频模型主要有反转链表。合并链表。快慢指针。删除节点。判环。其中最核心的 3 个模板是反转链表ListNodeprevnull;ListNodecurrhead;while(curr!null){ListNodenextcurr.next;curr.nextprev;prevcurr;currnext;}returnprev;虚拟头结点ListNodedummynewListNode(0,head);快慢指针ListNodeslowhead;ListNodefasthead;while(fast!nullfast.next!null){slowslow.next;fastfast.next.next;}动画辅助理解改指针前先保存后继链表题最适合用206. 反转链表建立第一印象。你可以先打开本地动画页链表反转链表分步动画这个动画最值得盯住的是 4 步先明确当前要处理的节点是cur已经反转好的部分头结点是prev。改cur.next之前必须先把原来的后继保存到next。再执行cur.next prev完成一个节点的局部反转。最后整体推进prev cur、cur next继续处理下一段链。拿1 - 2 - 3 - null举例状态变化可以这样记步骤当前状态关键操作为什么这样做初始prev null, cur 1还没改链先明确谁是已反转部分谁是待处理节点保存后继next 2ListNode next cur.next;不先保存后面一改cur.next就找不到2了局部反转1 - nullcur.next prev;把当前节点指回前驱完成一小段反转整体推进prev 1, cur 2prev cur; cur next;让下一轮继续处理原来的后继节点2. 这类题在面试里考什么链表题常见但能非常直接地看出候选人是否稳。面试官在看你是否清楚每个指针当前指向谁。你会不会因为修改顺序错误而把链断掉。你是否知道什么时候该加dummy。你是否理解快慢指针的语义而不只是机械套模板。很多候选人链表题不是败在思路而是败在“指针含义没说清、边界没提前想”。所以链表题的区分度往往就在这些细节上。3. 高频题清单题目来源难度高频属性206. 反转链表LeetCode 热题 100Easy面试高频21. 合并两个有序链表面试经典 150Easy基础高频19. 删除链表的倒数第 N 个结点LeetCode 热题 100Medium高频 Medium141. 环形链表LeetCode 热题 100Easy高频142. 环形链表 IILeetCode 热题 100Medium真实面经高频4. 这类题最容易犯的 3 个错误指针还没保存next就直接改链结果后续节点丢了。头结点可能变化的题不加dummy边界写得很乱。快慢指针会背但说不清为什么快指针先走n步。5. 代表题精讲 1题目206. 反转链表思路这题是链表基本功。核心在于把当前节点的next指向前一个节点所以每次循环都要做 4 件事先保存curr.next。再改curr.next prev。prev前进到curr。curr前进到原来的next。Java 代码classSolution{publicListNodereverseList(ListNodehead){ListNodeprevnull;ListNodecurrhead;while(curr!null){ListNodenextcurr.next;curr.nextprev;prevcurr;currnext;}returnprev;}}复杂度时间复杂度O(n)空间复杂度O(1)边界提醒这题最容易漏想的边界其实不复杂空链表和只有一个节点的链表。好消息是这套写法天然就能覆盖因为curr null时循环根本不会进入只有一个节点时执行一轮之后也会正确返回它自己。如果这是面试现场你可以这样说这题本质上是逐个节点把指针方向反过来。为了不丢链我会先保存当前节点的下一个节点再把当前节点的next指向前驱节点。prev表示已经反转好的部分头结点curr表示当前要处理的节点。整个过程只需要一次遍历。6. 代表题精讲 2题目19. 删除链表的倒数第 N 个结点思路这是快慢指针和dummy的组合题。为什么要加dummy因为被删除的节点可能正好是原头结点。为什么快指针先走n步这样当快指针走到链表末尾时慢指针刚好停在“待删除节点的前一个节点”方便删除。做法建dummy - head。fast先走n步。slow从dummy出发与fast一起走直到fast.next null。此时slow.next就是待删除节点执行删除。Java 代码classSolution{publicListNoderemoveNthFromEnd(ListNodehead,intn){ListNodedummynewListNode(0,head);ListNodefastdummy;ListNodeslowdummy;for(inti0;in;i){fastfast.next;}while(fast.next!null){fastfast.next;slowslow.next;}slow.nextslow.next.next;returndummy.next;}}复杂度时间复杂度O(n)空间复杂度O(1)边界提醒这里最关键的边界不是代码长短而是“删除的可能就是原头结点”。比如链表是1 - 2 - 3n 3真正要删的是第一个节点。如果你没有先建dummy就得单独处理头结点变化而加了dummy之后这个边界会自动归入统一流程。如果这是面试现场你可以这样说这题我会用虚拟头结点加快慢指针。先让快指针走n步这样快慢指针之间就保持了固定距离。之后它们一起走当快指针到达尾部时慢指针刚好停在待删除节点的前一个位置。用dummy可以统一处理删除头结点的边界。7. 其余题模板与关键片段21. 合并两个有序链表用dummy串起来ListNodedummynewListNode(0);ListNodetaildummy;while(list1!nulllist2!null){if(list1.vallist2.val){tail.nextlist1;list1list1.next;}else{tail.nextlist2;list2list2.next;}tailtail.next;}tail.next(list1!null)?list1:list2;这类题的核心不是“会不会连”而是你能不能保证tail始终指向已经合并好部分的最后一个节点。只要这个语义稳定代码就不容易乱。141. 环形链表Floyd 判环while(fast!nullfast.next!null){slowslow.next;fastfast.next.next;if(slowfast){returntrue;}}returnfalse;为什么它成立如果有环快指针每次比慢指针多走一步它们进入环之后距离会不断缩短最终一定会在环里相遇如果无环快指针会先走到null。8. 链表题先判断什么真正写代码前你可以先问自己 4 个问题这题会不会改动头结点。我现在改next之前后继节点有没有保存。这题更像反转 / 删除 / 合并还是快慢指针问题。我当前每个指针的语义能不能用一句话说清。这 4 个问题回答清楚链表题大部分错误都能提前拦下来。9. 错题本记录方式链表题建议重点记我是在哪一步把链断掉的。这题头结点会不会变化是否应该先加dummy。快慢指针里slow和fast分别表示什么。删除、反转、合并时哪一步最容易顺序写错。10. 面试前 3 分钟速记改链前先保存next。头结点可能变化优先想dummy。反转链表记住prev / curr / next。删除倒数第 N 个结点记住dummy fast先走n步。判环记住slow走1步fast走2步。11. 最后总结链表题的核心不是模板而是指针语义别乱如果你只能记住一句话那就是链表题真正难的地方不是模板多而是你必须始终知道“当前这几个指针分别指向谁”。面试时你可以按这个顺序去讲这题头结点会不会变化要不要先上dummy。我当前维护的每个指针分别表示什么。我改next之前是否已经把后继保存好了。这题的答案是返回prev、dummy.next还是某个相遇节点。这样你写出来的链表代码会稳定很多也更容易把思路讲清楚。上期速递【Java实习面试算法冲刺】滑动窗口下一篇正在路上……感谢阅读记得点赞、关注、收藏欢迎各位评论区交流