返回

LeetCode 237:在删除链表节点时保持优雅

闲谈

作为开发人员,我们经常需要在链表数据结构中添加或删除节点。特别是,删除链表节点 是一个经典问题,需要我们掌握扎实的链表基础和算法技巧。今天,我们将深入探讨 LeetCode 上的 237 题,探索如何优雅而高效地 完成此任务。

问题

给你一个链表的头节点 head 和一个节点 val,请你删除链表中第一个 值为 val 的节点,并返回新的头节点。

提示:

  • 链表中节点的值是唯一的。
  • 不会存在两个值为 val 的节点。

优雅的解决方案

解决这个问题的优雅解决方案是使用双指针技术:

  1. 定义两个指针: prev 指向当前节点的前驱节点,curr 指向当前节点。
  2. 初始化:prev 设置为虚拟头节点(指向实际头节点之前),curr 设置为头节点。
  3. 遍历链表:
    • 如果 curr 为空,则链表中不存在该节点,返回 prev.next(新的头节点)。
    • 如果 curr.val 等于 val,则将 prev.next 指向 curr.next,跳过 curr 节点。
    • 否则,将 prevcurr 都向前移动一步。
  4. 返回: 返回 prev.next,这是新的头节点。

代码实现

def deleteNode(head: ListNode, val: int) -> ListNode:
    prev = ListNode(0, head)
    curr = head

    while curr:
        if curr.val == val:
            prev.next = curr.next
            break
        else:
            prev = curr
            curr = curr.next

    return prev.next

优化与变体

  • 时间复杂度: O(n),其中 n 是链表的长度。我们必须遍历整个链表才能找到并删除节点。
  • 空间复杂度: O(1),因为我们只使用了恒定的额外空间。
  • 变体: 此算法还可以用于删除链表中的尾节点。在这种情况下,我们只需要一个指针(curr),并且在遍历到尾节点时将 prev 指向 null

总结

删除链表中的节点是链表编程中的一个基本操作。通过理解双指针技术,我们可以优雅高效地完成此任务。LeetCode 237 题提供了一个很好的机会来练习此技巧,并加深我们对链表数据结构的理解。通过持续的练习和创新,我们可以在算法和编程领域不断提升自己。