持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情。
大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流
作者简介:
- CSDN C/C++领域新星创作者blog.csdn.net/chuxinchang…
- 掘金LV3用户 juejin.cn/user/138142…
- 阿里云社区专家博主,星级博主,技术博主 developer.aliyun.com/profile/exp…
- 华为云云享专家 bbs.huaweicloud.com/community/m…
题目要求
给你一个链表的头节点 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, 104] 内 1 <= Node.val <= 50 0 <= val <= 50
解题思路
遍历链表进行对比,判断是不是要删除的结点
要保存释放结点的下一个结点,所以要定义两个指针。不然就找不到下一个结点了
cur:用于遍历链表,初始化 : 指向头结点
prev :保存cur的上一个结点 初始化为:NULL
-
如果cur指向的是要删除的结点:
- 先保存下一个结点 prev->next = cur->next
- 释放cur指向的结点 free(cur)
- 然后把cur指向下一个结点 cur = prev->next (prev->next就是原来cur的下一个结点)
-
如果cur指向的不是要删的结点:prev和cur迭代往后走
- prev保存现在cur的位置 prev = cur
- cur指向下一个位置 cur = cur -> next
特殊情况:要删除的是头结点
-
此时要释放原来的头结点,然后更改头指针的指向
-
步骤:
- 1.先保存头结点的下一个位置 cur = cur->next
- 2.释放头结点 free(head)
- 3.更改头指针的指向:head = cur
或者:
head = cur->next;//换头 free(cur);//释放原来的头结点 cur = head;//cur指向新的头
错误写法:
free(head);
head = cur->next;
cur = head;
错误原因:
提前释放了头结点,已经找不到它的下一个位置了
cur -> next 是野指针
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
//链表为空,返回空
if(head == NULL)
{
return NULL;
}
//定义两个指针,cur用于遍历,prev用于保存cur的上一个结点
struct ListNode* prev = NULL;//若prev最初也指向head是有风险的
struct ListNode* cur = head;
while(cur)
{
//如果cur指向的是要删的元素
if(cur->val == val)
{
//特殊情况:要删的是头
if(cur == head)
{
//释放原来的头结点,换头
head = cur->next;//换头
free(cur);//释放原来的头结点
cur = head;//cur指向新的头
}
else
{
prev->next = cur->next;//保存下一个结点
free(cur);//释放cur指向结点
cur = prev->next;//cur指向下一个结点
}
}
//如果cur指向的不是要删除的元素
else
{
//prev保存的是cur的前一个结点
prev = cur;//prev指向cur
cur = cur->next;//cur迭代往后走
}
}
return head;
}
prev若初始化为head的风险
为了保险起见:最初 prev = NULL
错误写法
和上面的不同点:
当cur指向的是要删除的结点时:
- 用prev保存cur的下一个结点
下面正确写法是:用prev->next指向cur的下一结点
struct ListNode* removeElements(struct ListNode* head, int val){
//链表为空,返回空
if(head == NULL)
{
return NULL;
}
//定义两个指针,cur用于遍历,prev用于保存cur的上一个结点
struct ListNode* prev = NULL;//若prev最初也指向head是有风险的
struct ListNode* cur = head;
while(cur)
{
//如果cur指向的是要删的元素
if(cur->val == val)
{
//特殊情况:要删的是头
if(cur == head)
{
//释放原来的头结点,换头
head = cur->next;//换头
free(cur);//释放原来的头结点
cur = head;//cur指向新的头
}
else
{
prev = cur->next;//保存下一个结点 ->有问题!!!!!!!
free(cur);//释放cur指向结点
cur = prev->next;//cur指向下一个结点
}
}
//如果cur指向的不是要删除的元素
else
{
prev = cur;//prev指向cur
cur = cur->next;//cur迭代往后走
}
}
return head;
}
错误原因:
\