leetcode
leetcode 2351 ~ 2400
拆分循环链表

拆分循环链表

难度:

标签:

题目描述

代码结果

运行时间: 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`指针的?
在拆分循环链表后,为了确保每个子链表都维持循环结构,需要调整两个关键节点的`next`指针。首先,将慢指针`slow`的`next`指针指向头节点`head`,这样从头节点到慢指针形成了一个闭环。其次,将快指针`fast`在结束遍历时所在的节点的`next`指针指向慢指针的下一个节点`slow.next`,确保从这个节点开始到链表的结束再回到此节点,形成第二个闭环。这样,两个子链表各自保持了循环链表的结构。
🦆
如果链表的节点总数是奇数,快慢指针的终止条件(快指针的下一节点或下下一节点为头节点)是否仍然有效?会不会影响中间节点的判断?
即使链表的节点总数是奇数,快慢指针的终止条件(快指针的下一节点或下下一节点为头节点)仍然有效。在奇数节点的链表中,快指针的终止位置仍然能确保慢指针大约位于链表的中间点。这是因为快指针每次移动两步,慢指针每次移动一步,无论节点总数是奇数还是偶数,快指针回到头节点时慢指针都会位于中间位置的附近。这种方法能适应链表节点数的奇偶变化,不会影响到中间节点的正确判断。

相关问题