链表双指针技巧
题目 | 难度 | 要点 |
---|---|---|
分隔链表 | ● | 快慢指针:不用两个新链表拼接,使用原地修改 |
合并K个升序链表 | ● | 最小堆:类ProirityQueue的使用 |
环形链表 | ● | 快慢指针:相遇有环 |
环形链表II | ● | 快慢指针:入环第一个节点 |
分隔链表
题目要求按原顺序,以x值将小的放链表前半段,其他的放链表后半段。很容易想到一种解法,新开两条链表分别存放,最后将两条链表合并。题目难度给个中等,可以考虑换个复杂点的原地修改解法。那么需要了解2个地方的信息:1.待插入的节点 2.需要移动的节点。很容易就可以想到快慢指针,慢指针等待插入,快指针寻找小于x的节点,进行操作即可。
public ListNode partition(ListNode head, int x) { ListNode dummy = new ListNode(-1, head); ListNode slow = dummy; while (slow.next != null && slow.next.val < x) { slow = slow.next; } ListNode fast = slow; while (fast != null && fast.next != null) { if (fast.next.val < x) { ListNode temp = fast.next; fast.next = temp.next; temp.next = slow.next; slow.next = temp; slow = slow.next; } else { fast = fast.next; } } return dummy.next; }
合并K个升序链表
两个链表合并的升级版。JAVA没有大小堆的直接类,但是优先级队列类底层默认为最小堆,可指定Comparator变为最大堆。
思路:首先放链表个数的节点到最小堆中,每次取出最小的置于新链表。如果节点有子节点则加入优先级队列自动排序。重复步骤直到队列为空即可。
public ListNode mergeKLists(ListNode[] lists) { if (lists == null || lists.length == 0) { return null; } ListNode dummy = new ListNode(), p = dummy; PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, (a, b) -> (a.val - b.val)); for (ListNode node: lists) { if (node != null) { pq.add(node); } } while (!pq.isEmpty()) { ListNode node = pq.poll(); if (node.next != null) { pq.add(node.next); } p.next = node; p = p.next; } return dummy.next; }
环形链表
快慢指针经典题,两个指针相遇即有环,否则无环。
public boolean hasCycle(ListNode head) { ListNode slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { return true; } } return false; }
环形链表II
环形链表升级,返回入环的第一个节点。借用截图中例子,任意假设0节点相遇,那么此时slow跑了长度n,fast跑了长度2n。假设2节点到0节点长度为k,那么通过slow可得3节点到2节点长度为n-k,通过fast(fast比slow多跑了一个圈)可得-4节点到2节点长度为2n-n-k=n-k。那么slow或fast重置为head,都单步前进直到相遇即答案。
public ListNode detectCycle(ListNode head) { ListNode slow = head, fast = head; // 判断是否有环 while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { break; } } if (fast == null || fast.next == null) { return null; } // 寻找入环第一个节点 slow = head; while (slow != fast) { slow = slow.next; fast = fast.next; } return slow; }
··
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义