拆分循环链表
难度:
标签:
题目描述
代码结果
运行时间: 385 ms, 内存: 40.2 MB
/*
* Leetcode 2674: Split a Circular Linked List
*
* 使用Java Stream的解法实现思路:
* 1. 由于链表操作在Stream中较为复杂,Stream并不适用于本题
* 2. 因此,保持与普通Java解法相同的逻辑,但通过更多的函数式编程风格来实现
*/
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class SplitCircularLinkedListStream {
public ListNode[] splitCircularLinkedList(ListNode head) {
if (head == null || head.next == head) {
return new ListNode[] { head, null };
}
ListNode slow = head, fast = head;
while (fast.next != head && fast.next.next != head) {
slow = slow.next;
fast = fast.next.next;
}
ListNode head1 = head;
ListNode head2 = slow.next;
slow.next = head1;
ListNode curr = head2;
while (curr.next != head) {
curr = curr.next;
}
curr.next = head2;
return new ListNode[] { head1, head2 };
}
}
解释
方法:
该题解采用的是快慢指针法来找到循环链表的中间节点。快指针每次移动两步,慢指针每次移动一步。当快指针的下一节点或下下一节点为头节点时,循环终止,此时慢指针所在的节点即为链表的中间节点。接下来,将链表从中间节点拆分为两部分:一部分是头节点到中间节点,另一部分是中间节点的下一个节点到链表结束。然后重新调整节点的next指针,使得两个子链表各自形成循环链表。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在使用快慢指针来查找循环链表的中间节点时,你是如何确定循环应当在什么条件下结束?
▷🦆
请解释为什么在快指针的下一节点或下下一节点为头节点时,我们可以认为慢指针已经到达了链表的中间部分。
▷🦆
在拆分链表后,如何确保每个子链表都能保持循环链表的结构?具体是如何调整每个链表的`next`指针的?
▷🦆
如果链表的节点总数是奇数,快慢指针的终止条件(快指针的下一节点或下下一节点为头节点)是否仍然有效?会不会影响中间节点的判断?
▷