题目描述
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
![](https://img-blog.csdnimg.cn/b4ea4acf162346688392c2aa86ecb5f3.png)
思路
将结点值不等于val的结点,逐个尾插到新链表
步骤
分析
- 需要创建一个头结点,来保存新链表的位置
- 需要创建一个循环,遍历链表,找出目标结点
- 循环内分为两个部分,部分一:尾插结点值非val的结点;部分二:删除结点值为val的结点
![](https://img-blog.csdnimg.cn/3a4cb5e063a64bce9130d69363022149.png)
具体流程
- 创建一个新的头指针newHead和尾指针tail
- 开辟一个新结点,作为哨兵位的头结点,并将newhead和tail指向该结点
- 创建一个指针cur,指向原链表的头结点head
- 开始遍历链表,通过while循环判断当前结点cur是否为空
- 如果当前结点cur的值不等于val,则将该结点尾插到新链表
- 将tail结点的next指针指向cur
- 更新tail为cur,记录新的尾结点
- 迭代cur指向下一个结点cur->next
- 如果当前结点的值等于val,则删除该结点
- 创建一个del指针,指向cur,用于释放结点内存
- 迭代cur指向下一个结点cur->next,避免结点释放后,找不到下一个结点
- 释放del指向的结点内存
- 遍历结束后,将新链表的尾结点tail的next指针置空,标记新链表结束,同时防止访问内存释放了的结点
- 由于新链表的头结点是一个哨兵位,有效结点从哨兵位的next指针开始。因此,将newHead的next指针赋值newList指针
- 然后释放哨兵位的内存
- 返回newList指针
代码
ListNode* removeElements(ListNode* head, int val)
{
ListNode* newHead = nullptr;
ListNode* tail = nullptr;
newHead = tail = (ListNode*)malloc(sizeof(ListNode));
newHead->next = nullptr;
ListNode* cur = head;
while(cur)
{
//尾插结点
if(cur->val != val)
{
tail->next = cur;
tail = cur; //更新尾结点
cur = cur->next; //迭代当前结点
}
//删除等于val的结点
else
{
ListNode* del = cur;
cur = cur->next;
//free(del);
delete del; //注意new申请的结点内存,不能用free释放
}
}
tail->next = nullptr; //置空新链表尾结点的next指针
ListNode* newList = newHead->next;
free(newHead); //释放哨兵位
return newList;
}
复杂度分析
-
时间复杂度为O(N),N为链表结点个数,只需遍历一次链表,就可以删除结点值等于val的结点
-
空间复杂度为O(1),函数removeElements运行过程中,只额外开辟了1个结构体指针变量