摸鱼时卷王在疯狂刷题,这我可忍不了-<移除链表元素>

简介: 移除链表元素

题目要求

链接:https://leetcode-cn.com/problems/remove-linked-list-elements/description/

4e4a423b648f4a6b9e9ef1da4b5f5db9.png

解题思路

遍历链表进行对比,判断是不是要删除的结点

a0068b055823419891447a2305612524.png


要保存释放结点的下一个结点,所以要定义两个指针。不然就找不到下一个结点了

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 是野指针

546c98e9eb5c4e2687d54d6a6dfc4311.png

代码

/**
 * 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的风险

546c98e9eb5c4e2687d54d6a6dfc4311.png

为了保险起见:最初 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;
}

错误原因:

75717786acdd427f86a68a07138ada9e.png

相关文章
|
2月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
37 1
01_移除链表元素
01_移除链表元素
|
2月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
33 0
|
4月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
4月前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
4月前
|
存储 C语言
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
|
4月前
|
机器学习/深度学习
【刷题记录】相交链表
【刷题记录】相交链表
|
4月前
【刷题记录】链表的中间结点
【刷题记录】链表的中间结点
|
6月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
6月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表