当前位置: 首页 > article >正文

L5.【LeetCode笔记】移除链表元素

1.题目

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

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

示例 1:f7ef6957ec5e426b869e88457ccc368b.jpeg

输入: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
  • 代码模板
  • /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    struct ListNode* removeElements(struct ListNode* head, int val) 
    {
    }

2.自解

算法:双指针一次遍历

不加思索写出以下代码

struct ListNode* removeElements(struct ListNode* head, int val) 
{
    if (head==NULL)
    return NULL;
    struct ListNode* prev=NULL;
    struct ListNode* cur=head;
    while(cur)
    {
        if (cur->val!=val)
        {
            prev=cur;
            cur=cur->next;
        }
        else
       {
            prev->next=cur->next;
            free(cur);
            cur=prev->next;
       }
    }
    return head;
}

会发现报错(null pointer)

45a0db54678148ddb952680c00ded403.png 分析: 当头结点的需要删除时,执行if判断的else部分

        else
       {
            prev->next=cur->next;
            free(cur);
            cur=prev->next;
       }

prev->next为NULL->next,这是非法的

 因此需要先判断prev是否为NULL,如果为NULL则头删(注意:头删一定要移动头结点)

        if (cur->val!=val)
        {
            prev=cur;
            cur=cur->next;
        }
        else
       {
            if (prev==NULL)
            {
                head=cur->next;
                free(cur);
                cur=head;
            }
            else
            {
                prev->next=cur->next;
                free(cur);
                cur=prev->next;
            }
       }

其他注意事项:特殊情况优先判断:是否为空链表

    if (head==NULL)
    return NULL;

 完整代码为:

/**
 * 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;
    struct ListNode* prev=NULL;
    struct ListNode* cur=head;
    while(cur)
    {
        if (cur->val!=val)
        {
            prev=cur;
            cur=cur->next;
        }
        else
       {
            if (prev==NULL)
            {
                head=cur->next;
                free(cur);
                cur=head;
            }
            else
            {
                prev->next=cur->next;
                free(cur);
                cur=prev->next;
            }
       }
    }
    return head;
}

提交结果:

553dea3539784e27add4050c33dbc266.png

3.其他解法 

尾插算法,需要找尾,因此需要尾指针tail

不加思索写出以下代码

/**
 * 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;
    struct ListNode* newhead=NULL;
    struct ListNode* tail=NULL;
    struct ListNode* cur=head;
    while(cur)
    {
        if (cur->val!=val)
        {
            if (tail==NULL)
            {
                newhead=tail=cur;
            }
            else
            {
                tail->next=cur;
                tail=tail->next;
            }
            cur=cur->next;
        }
        else
        {
            struct ListNode* next=cur->next;
            free(cur);
            cur=next;
        }
    }
    return newhead;
}

e5e9d622319d4f3ba9345d4bc3c57e83.png

注意到heap-use-after-free,不可用指针访问已经被释放的内存空间(野指针行为)

在尝试头删,中间删和尾删后,发现尾删出了问题

设原链表为[1,2,3],val=3,画图为

添加对tail的判断,改成下面这样就行

        else
        {
            struct ListNode* next=cur->next;
            free(cur);
            cur=next;
        }
    }
     if (tail)
        tail->next=NULL;
    return newhead;
}

 完整代码为

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    struct ListNode* newhead=NULL;
    struct ListNode* tail=NULL;
    struct ListNode* cur=head;
    while(cur)
    {
        if (cur->val!=val)
        {
            if (tail==NULL)
            {
                newhead=tail=cur;
            }
            else
            {
                tail->next=cur;
                tail=tail->next;
            }
            cur=cur->next;
        }
        else
        {
            struct ListNode* next=cur->next;
            free(cur);
            cur=next;
        }
    }
    if (tail)
        tail->next=NULL;
    return newhead;
}

提交结果:


http://www.kler.cn/a/381951.html

相关文章:

  • 【毫米波雷达(八)】车载毫米波前雷达遮挡检测功能
  • OpenAI 发布了新的事实性基准——SimpleQA
  • npm入门教程1:npm简介
  • 黑马官网2024最新前端就业课V8.5笔记---HTML篇
  • 【Java SE语法】重载(overload)和重写(override)一样吗?它们的区别是什么?
  • Ghidra无头模式(自动化批处理执行重复性任务)
  • 如何修改远程分支?修改了会影响什么?
  • python中t是什么意思
  • 直播系统搭建教程安装说明
  • IT架构管理
  • SpringBoot在线教育系统:性能监控与优化
  • 项目活动进度计算题
  • arkUI:布局的属性(margin、padding、border、borderRadius)
  • Spring Boot驱动的多维分类知识管理系统
  • 雷池社区版 7.1.0 LTS 发布了
  • U8C表体存货或编码相关的字段赋值不上
  • Pr 视频效果:超级键
  • 文件外发记录监控 | 公司文档外发如何跟踪数据流向?6大策略让文件不再滥发泄密! (2024全面解读)
  • 高效率的快捷回复软件 —— 客服宝聊天助手
  • 搜维尔科技:SenseGlove案例-利用VR触觉技术培训机组人员
  • Netty原来就是这样啊(二)
  • VBA06-组件
  • 开车去内蒙古旅游要做什么准备?
  • rabbitMq双节点高可用集群安装(亲测可用)
  • 数据分析反馈:提升决策质量的关键指南
  • RabbitMQ应用问题