Leetcode 203. 移除链表元素

389 阅读2分钟

原题链接: 203. 移除链表元素 - 力扣(Leetcode)

tag: 链表.

一. 题目

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

二. 题解

当要对链表中的节点的进行删除操作时, 必然会涉及头删的情况.

而删除链表的节点的一般方法是锚定待删除节点的前驱节点, 修改前驱节点的 next 指针, 使其指向待删除节点的后继节点, 再 delete 待删除的节点, 即可完成删除操作.

然而头节点没有前驱节点, 当删除头节点时, 我们需要进行额外的讨论.

为了避免这种额外的讨论, 我们引入虚拟头节点( dummy )的概念.

设置虚拟头节点, 即在链表的头节点前新插入一个节点. 如此, 链表的头节点便有了前驱节点(即 dummy), 头删时就不需要进行额外的讨论.

移除元素前.

image.png

设置一个虚拟头节点 dummy.

ListNode* dummy = new ListNode(0, head);

image.png

开始对指定元素所在节点进行删除操作.

ListNode* curr = dummy;

image.png

ListNode* temp = curr->next;

image.png

curr->next = temp->next;

image.png

delete temp;

image.png

逐一检测每个节点中的元素值, 若是指定元素, 则移除该元素; 若不是指定元素, 则 curr 指针向后移一步.

curr 指针向后移一步.

curr = curr->next;

image.png

curr 指针向后移一步.

curr = curr->next;

image.png

curr 指针向后移一步.

curr = curr->next;

image.png

curr->next == nullptr 时, 链表中所有的节点都被遍历一次, 指定元素都已经被移除完毕.

image.png

返回新的头节点.

head = dummy->next;

image.png

delete dummy;

image.png

移除元素后.

image.png

三. 复杂度分析

时间复杂度: O(N), 其中 N 是链表的长度, 完成对指定元素的移除需要遍历一次链表.

空间复杂度: O(1).

四. 代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummy = new ListNode(0, head);    // 设置一个虚拟头节点
        ListNode* curr = dummy;
        while (curr->next != nullptr) {    
            if (curr->next->val == val) {    // 对指定元素所在节点进行删除操作
                ListNode* temp = curr->next;
                curr->next = temp->next;
                delete temp;
            } else {    // curr 指针向后移一步
                curr = curr->next;
            }
        }
        head = dummy->next;    // 返回新的头节点
        delete dummy;
        return head;
    }
};