📜  删除链表中间(1)

📅  最后修改于: 2023-12-03 15:22:44.436000             🧑  作者: Mango

删除链表中间(Delete Middle Element from Linked List)

当面临删除链表中间元素时,我们需要考虑删除的节点究竟是哪个,因为链表的中间节点数可能为偶数或奇数。以下是我们将要讨论的方案:

  • 删除中间节点
  • 删除中间节点的前驱节点
  • 删除中间节点的后继节点
删除中间节点

对于有奇数个节点的链表,中间节点就是第 n/2 + 1 个节点,其中 n 是链表中节点的总数。对于有偶数个节点的链表,我们取中间的两个节点中的任意一个作为中间节点。下面的示例演示了删除链表中间节点的方法:

public ListNode deleteMiddleNode(ListNode head) {
    if (head == null) {
        return null;
    }
    if (head.next == null) {
        return null;
    }
    ListNode slow = head;
    ListNode fast = head;
    ListNode prev = null;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        prev = slow;
        slow = slow.next;
    }
    prev.next = slow.next;
    return head;
}

上述代码中,我们使用双指针法,其中第一个指针每次向前移动一个节点,第二个指针则每次向前移动两个节点。当第二个指针到达链表末端时,第一个指针就指向了中间节点。通过保留删除节点的前驱节点,我们可以使用 prev.next = slow.next 代码语句来删除中间节点。

删除中间节点的前驱节点

有时候我们需要删除中间节点的前驱节点。这种情况通常发生在删除双向链表(doubly linked list)中的某个节点时。下面的代码演示了如何删除链表中间节点的前驱节点:

public ListNode deletePrevOfMiddleNode(ListNode head) {
    if (head == null) {
        return null;
    }
    if (head.next == null) {
        return null;
    }
    ListNode slow = head;
    ListNode fast = head;
    ListNode prev = null;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        prev = slow;
        slow = slow.next;
    }
    prev.prev.next = prev.next;
    if (prev.next != null) {
        prev.next.prev = prev.prev;
    }
    return head;
}

在上述代码中,我们不仅需要保留删除节点的前驱节点,还需要记录前驱节点的前驱节点(即 prev.prev)。通过 prev.prev.next = prev.next 代码语句,我们可以跳过要删除的前驱节点(同时将其前驱节点的 next 指针直接指向其后继节点)。如果被删除的前驱节点这时此节点后面还有后继节点的话,还需要更新此后继节点的 prev 指针。

删除中间节点的后继节点

有时候我们需要删除中间节点的后继节点。以下是如何实现该操作的示例代码:

public ListNode deleteSuccOfMiddleNode(ListNode head) {
    if (head == null) {
        return null;
    }
    if (head.next == null) {
        return null;
    }
    ListNode slow = head;
    ListNode fast = head;
    ListNode prev = null;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        prev = slow;
        slow = slow.next;
    }
    if (slow.next != null) {
        slow.next = slow.next.next;
    }
    return head;
}

上述代码中,我们只需要更改被删除节点的后继节点的位置即可。通过使用 slow.next = slow.next.next 代码语句,我们就可以直接删除中间节点的后继节点。

我们可以使用上述任何一种方法来删除链表中间节点。具体取决于我们需要删除节点的前驱节点还是后继节点。