Skip to content

203.移除链表元素

一、 问题描述

删除链表中等于给定值 val 的所有节点。

示例

go
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

二、方案一:迭代法

1、思路

  • 使用一个哑节点作为新链表的头部,这样可以避免处理头部节点的特殊情况。
  • 遍历链表,当当前节点的下一个节点的值等于 val 时,跳过这个节点。

2、代码实现

go
func removeElements(head *ListNode, val int) *ListNode {
    // 创建哨兵节点,其Next指向head
    sentinel := &ListNode{Next: head}
    // 初始化当前节点为哨兵节点
    current := sentinel
    // 遍历链表
    for current.Next != nil {
        // 如果当前节点的下一个节点的值等于给定值
        if current.Next.Val == val {
            // 跳过这个节点
            current.Next = current.Next.Next
        } else {
            // 否则,移动到下一个节点
            current = current.Next
        }
    }
    // 返回哨兵节点的下一个节点作为新链表的头部
    return sentinel.Next
}

3、复杂度分析

  • 时间复杂度:O(n),其中 n 是链表的长度。
  • 空间复杂度:O(1)。

三、方案二:递归法

1、思路

  • 递归的基本思想是先处理子问题,然后再处理当前问题。
  • 对于当前节点,先递归地移除其所有子节点中的 val
  • 然后判断当前节点的值是否等于 val,如果是,则返回其下一个节点;否则,返回当前节点。

2、代码实现

go
func removeElements(head *ListNode, val int) *ListNode {
    // 如果链表为空,直接返回空
    if head == nil {
        return nil
    }
    // 递归地删除头节点的下一个节点
    head.Next = removeElements(head.Next, val)
    // 如果头节点的值等于给定值,返回头节点的下一个节点
    // 否则,返回头节点
    return head.Val == val ? head.Next : head
}

3、复杂度分析

  • 时间复杂度:O(n),其中 n 是链表的长度。
  • 空间复杂度:O(n),递归栈的深度。

四、总结

方案时间复杂度空间复杂度备注
迭代法O(n)O(1)使用哑节点简化操作
递归法O(n)O(n)递归实现,代码简洁

迭代法在空间复杂度上更优,递归法在代码简洁性上更优。根据实际情况选择适合的方法。

木川工作室 (微信:mcmc2024)