LeetCode 203.移除链表元素 c语言题解
此题有两种思路:
- 在原链表上直接删除需要移除的结点
- 重新定义一个链表,不是需要删除的结点则链接上,是需要删除的结点则删除跳过
每一种思路的更详细的注释说明在下方代码中
可以帮助你更好的理解单链表的增删查改的应用
思路一:`
struct ListNode* removeElements(struct ListNode* head, int val)
{
//思路一:重新定义一个链表
struct ListNode* cur = head;
struct ListNode* newhead = NULL;
struct ListNode* tail = NULL;
//cur依次遍历结点,用于判断什么结点链上,什么结点不链上,直到空结点循环结束
while(cur)
{
//如果不是待删除结点,链上,否则,跳过+删除
//链上分两种情况,跟链表尾插一个道理
//1.链表为空
//2.链表不为空
//是待删除结点
if(cur->val!=val)
{
//1.链表为空
if(tail == NULL)
{
tail = newhead = cur;
cur = cur->next;
}
//2.链表不为空
else
{
tail->next = cur;
tail = cur;
cur = cur->next;
}
}
//不是待删除结点
else
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
del = NULL;
}
}
//这里需要画图才好理解
//就拿原题中的例子来说,如果最后一个结点是待删除结点,那么当释放掉最后一个结点后,
//原链表的最后一个结点依然指向这个待删除结点.因此需要最后一步置空
//当然,这样置空的前提链表不是空链表,否则会出现越界
if(tail)
{
tail->next = NULL;
}
//最后不要忘了返回新的头结点
return newhead;
}
思路二:
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* cur = head;
struct ListNode* prev = NULL; //prev用于跟在cur后面,删除跳过cur指向的结点
//同上,cur遍历链表,是待删除元素则跳过删除
//单链表删除分两种情况:
//1.头删:直接记录当前结点,头结点跳过当前结点,再free掉当之前的头结点
//2.非头删:当前结点需要有前一个结点的辅助,因此我们定义了一个prev结点
while(cur)
{
//是待删除元素
//分两种情况:是头结点 不是头结点
if(cur->val == val)
{
//1.是头结点
if(cur == head)
{
head = head->next;
free(cur);
cur = head;
}
//2.不是头结点
else
{
prev->next = cur->next;//跳过
free(cur);
cur = prev->next;
}
}
//不是待删除元素,prev紧跟cur其后
else
{
prev = cur;
cur = cur->next;
}
}
//这里与思路一有所不同,画图克制,最后prev = cur,而cur==NULL,
//所以最后不用置空了
return head;
}