题目
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
思路设计
方法一
考虑到可能会删除头节点的情况,我们在头节点前添加一个哑节点dummyNode,这样就可以想处理其他节点一样处理头节点了。
直接从头节点遍历链表,符合删除条件时直接删除就好。返回节点的时候直接返回dummyNode->next,不要返回头节点,以防头节点被删了。
上代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* dummyNode没有初始化,所以会报错,但其他处理逻辑是没有错的,大家初始化后就不会报错了。
*/
struct ListNode *removeElements(struct ListNode *head, int val)
{
struct ListNode *dummyNode;
dummyNode->next = head; //头节点前添加哑节点
struct ListNode *node = dummyNode;
while (node->next)
{
if (val == node->next->val)
{
node->next = node->next->next; //删除节点后不能让 node = node->next
}else{ // 当出现连续两个节点都需要删除时,如果没有 else ,直接node = node->next就会把第二个需要删除的节点漏掉
node = node->next;
}
}
return dummyNode->next;
}
方法二
对头节点可能出现的特殊情况进行讨论处理。头节点为空、头节点需要被删除
上代码
struct ListNode *removeElements(struct ListNode *head, int val)
{
//头节点需要被删除
while (head && val == head->val)
{
head = head->next;
}
// 头节点为空
if (!head)
{
return head;
}
struct ListNode *node = head;
while (node&&node->next) // 使用next指针时必须判断当前节点是否存在,所以必须判断 node是否存在
{
if (val == node->next->val)
{
node->next = node->next->next;
}else{
node = node->next;
}}
return head; // 头节点虽然可能被删,但删除后头节点的变量名依然是head
}
复杂度分析
时间复杂度
以上两个方法都只对链表遍历了一遍,操作次数为n,所以时间复杂度为 O(n)
空间复杂度
以上两个方法都只使用了常量级的指针,空间复杂度为O(1)