题目描述:
给你一个链表的头节点 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
输出:[]
提示:
列表中的节点数目在范围 [0, 10^4] 内
1 <= Node.val <= 50
0 <= val <= 50
思考与总结:
链表节点的定义:
//单链表
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x): val(x), next(NULL) {} // 节点的构造函数
};
关于构造函数,C++默认生成一个构造函数,但这个构造函数不会初始化任何成员变量,举例如下:
//自己定义构造函数初始化节点
ListNode* head = new ListNode(5);
//使用默认构造函数初始化节点
ListNode* head = new ListNode();
head->val = 5;
删除节点时,C++里要手动释放节点内存,其他语言如Java、Python,有自己的内存回收机制,不需要手动释放。
增加和删除的时间复杂度是O(1),但查找的时间复杂度为O(n)。
链表删除操作的两种方式:
1、直接使用原来的链表进行删除操作,这样会发现单链表中移除头节点和移除其他节点的操作方式不一样,需要单独写一段逻辑来处理移除头节点的情况;
2、设置一个虚拟头节点再进行删除操作,这样可以以一种统一的逻辑来移除链表的节点。
代码示例:
//直接使用原来的链表来进行移除节点操作
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head != NULL && head->val == val) {
ListNode* tmp = head;
head = head->next;
delete tmp;
}
ListNode* cur = head;
while(cur != NULL && cur->next != NULL) {
if(cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}
else {
cur = cur->next;
}
}
return head;
}
};
//设置一个虚拟头节点再进行移除节点操作
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dumptyNode = new ListNode(0);
dumptyNode->next = head;
ListNode* cur = dumptyNode;
while(cur->next != NULL) {
if(cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}
else {
cur = cur->next;
}
}
head = dumptyNode->next;
delete dumptyNode;
return head;
}
};