删除中间节点

标签: 链表

难度: Easy

若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。

假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。

例如,传入节点 c(位于单向链表 a->b->c->d->e->f 中),将其删除后,剩余链表为 a->b->d->e->f

 

示例:

输入:节点 5 (位于单向链表 4->5->1->9 中)
输出:不返回任何数据,从链表中删除传入的节点 5,使链表变为 4->1->9

 

Submission

运行时间: 48 ms

内存: 14.8 MB

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        node.val = node.next.val
        node.next = node.next.next

Explain

该题解的核心思路是通过复制节点的方式实现删除操作。具体做法是将待删除节点的下一个节点的值复制到当前节点,然后将当前节点的next指针指向下下个节点,这样就相当于删除了原节点的下一个节点,间接达到了删除当前节点的效果。由于直接修改了链表结构,因此无需返回任何值。

时间复杂度: O(1)

空间复杂度: O(1)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        删除指定节点,通过将下一节点的值复制到当前节点,并将当前节点的next指针指向下下个节点,实现删除。
        """
        node.val = node.next.val  # 将下一节点的值复制到当前节点
        node.next = node.next.next  # 跳过下一节点,实现删除效果

Explore

如果待删除节点是链表中的倒数第二个节点,其`next.next`将是`None`,因为`next`指向的是最后一个节点,而最后一个节点的`next`是`None`。在这种情况下,可以正常复制倒数第一个节点的值到倒数第二个节点,并将倒数第二个节点的`next`设置为`None`,从而删除倒数第一个节点。

该算法并没有直接考虑待删除节点为链表尾节点的情况。由于算法依赖于节点后续的存在(至少需要一个后续节点来复制其值),因此如果`node.next`为`None`(即节点为尾节点),则无法执行此删除方法。这种方法仅适用于非尾部节点。

这种删除方法假设待删除的节点不是头节点,因为它依赖于节点的前驱节点(即至少存在一个节点在待删除节点之前)。在这种方法中,没有直接访问或修改前驱节点,而是通过修改当前节点的值和指针来实现删除效果。因此,这种方法不适用于头节点,因为头节点没有前驱节点。

删除操作通过修改值和指针来'伪删除'节点,实际上并没有从内存中移除节点。如果其他变量或数据结构引用了被删除的节点,它们将看到值被修改后的状态。例如,如果有一个变量引用了被'删除'的节点,那么该变量现在将引用一个值被改变且`next`指针被重定向的节点。这可能导致不一致和意外的行为,特别是在并发环境中。