leecode-移除链表元素

203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

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

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

这里我使用到哑指针用于保存head的地址,这里cur表示当前遍历到的结点,分三种情况

第一种 cur的后两个节点都存在并且后一个元素要移除(相当于示例1中的第1个6),只要cur->next = cur->next->next;

第二种,cur是倒数第二个元素并且最后一个元素要移除(相当于示例1中的第二个6),只要让cur的next指针指向空就可以了

第三种,cur后一个元素不需要移除,就把cur后移一位。

ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummy = new ListNode(0, head);
        ListNode* cur = dummy;
        while (cur->next) {
            if (cur->next->val == val && cur->next->next)
                cur->next = cur->next->next;
            else if (cur->next->val == val)
                cur->next = NULL;
            else
                cur = cur->next;
        }
        return dummy->next;
    }

递归做法

ListNode* removeElements(ListNode* head, int val) {
        if (head == NULL)
            return head;
        head->next = removeElements(head->next, val);
        if (head->val == val)
            return head->next;
        else
            return head;
    }

### 如何实现移除链表中的指定元素 #### 方法概述 移除链表中指定元素可以通过多种方法实现,常见的有直接修改原链表、创建新链表以及引入哨兵节点的方式。以下是具体实现细节。 --- #### 方法一:在原链表中删除目标元素 此方法通过遍历链表并调整指针来跳过需要删除的目标节点。为了处理特殊情况(如头节点即为目标节点),可以引入虚拟头节点简化逻辑[^1]。 ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def removeElements(head: ListNode, val: int) -> ListNode: dummy_head = ListNode(next=head) # 创建虚拟头节点 prev, cur = dummy_head, head # 初始化两个指针 while cur is not None: # 遍历整个链表 if cur.val == val: # 如果当前节点是要删除的值 prev.next = cur.next # 跳过该节点 else: prev = cur # 更新前驱节点 cur = cur.next # 移动到下一个节点 return dummy_head.next # 返回新的头节点 ``` 这种方法的时间复杂度为 O(n),空间复杂度为 O(1)[^4]。 --- #### 方法二:新建一个链表并将不需要删除的元素尾插进来 此方法通过构建一个新的链表,仅保留不等于目标值的节点。这种方式无需显式地管理复杂的边界条件,因此代码更加简洁明了[^2]。 ```python def removeElements(head: ListNode, val: int) -> ListNode: new_dummy = ListNode() # 新建虚拟头节点 tail = new_dummy # 定义尾部指针 current = head # 原链表起始点 while current is not None: # 遍历原链表 if current.val != val: # 只插入非目标值的节点 tail.next = ListNode(current.val) tail = tail.next current = current.next # 继续遍历 return new_dummy.next # 返回新链表头部 ``` 虽然这种做法简单易懂,但由于每次都需要分配新的内存单元存储复制的数据,其空间开销较大[^3]。 --- #### 方法三:利用带哨兵位的头结点优化实现 基于上述两种方案的优点,在实际应用时常采用带有假头节点的方法进一步提升效率和可读性。它不仅能够有效规避单独判断首元的情况,还保持较低的空间占用率。 伪代码如下所示: ```python def removeElementsWithSentinel(head: ListNode, val: int) -> ListNode: sentinel = ListNode(-1) # 构造哨兵节点 sentinel.next = head # 连接原始列表 previous, current = sentinel, head while current: if current.val == val: previous.next = current.next # 删除匹配项 else: previous = current # 正常移动previous current = current.next # 不管怎样都要前进current return sentinel.next # 输出最终结果 ``` 以上程序片段清晰展示了如何借助辅助结构完成任务的同时维持较高的性能指标[^4]。 --- ### 总结 综上所述,针对不同场景可以选择适合自己的解决方案。如果追求极致速度且允许额外消耗,则推荐重构全新序列;反之则优先考虑就地更新策略配合适当技巧减少冗余运算次数即可达成目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值