选自力扣题目。
该题有两个解题思路:
1:遍历链表,保存当前节点的地址(list)以及当前节点的上一个节点的地址(prevpos),在遇到待删节点时,令prevpos->next=list->next;
struct ListNode* removeElements(struct ListNode* head, int val) {
struct ListNode* prevpos = NULL;
struct ListNode* cur = NULL;
if (head == NULL)//判断头节点是否为空,即是否为空链表
return head;
if (head->val == val)//判断是否头节点就是要删除的节点
{
while (head->val == val)//可能存在多个连续的节点均为目标节点
{
head = head->next;
if (head == NULL)
break;
}
}
if (head == NULL)//删除完头节点后可能链表就被删空,所以需要再次判断
return head;
struct ListNode* list = head;//如果链表不为空,则创建list
if(head->val != val)
{
while (list != NULL)//遍历链表
{
if (list->val == val)//如果遇到目标节点
{
cur = head;
while (cur->val != val)//找到目标节点的前一个节点地址
{
prevpos = cur;
cur = cur->next;
}
prevpos->next = list->next;//令目标节点的前一个节点地址指向目标节点的下一个节点地址
}
list = list->next;
}
}
return head;//返回头节点
}
2.从逻辑上建立新的链表(实质上并没有新创建链表,只是将原链表中非目标节点重新链接起来),建立newhead,tail,cur变量,其中newhead,tail分别模拟xin链表中的头和尾,利用cur遍历原链表,将非目标节点放入新链表中。
struct ListNode* removeElements(struct ListNode* head, int val)
{
ListNode* newhead = NULL;
ListNode* tail = NULL;
ListNode* cur = head;
while (cur)
{
if (cur->val == val)//如果链表第一个节点就是目标节点,则无需“拷贝”,直接释放掉该节点
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
}
else
{
if (tail == NULL)//当新链表还没有任何节点插入时
newhead = tail = cur;
else //尾插至新链表
{
tail->next = cur;
tail = tail->next;
}
cur = cur->next;
}
}
if (tail)//有可能原链表最后一个节点不是目标节点,则tail->next不为空,所以必须有该判断,详情见图
tail->next = NULL;
return newhead;
}