每日一题(移除链表元素)

简介: 每日一题(移除链表元素)

每日一题(移除链表元素)


203. 移除链表元素 - 力扣(LeetCode)


aa36964343dd57ffa2527d52f44c7776_1a54ebeea97547a391323ffd612abe21.png


思路一:


可以创建一个新的链表头节点newhead,只要是原链表中值不为val的节点、都通过尾插操作插到newhead所指向的链表中,原链表中值为val的节点直接删除释放掉。为了让尾插操作更方便,还需要再定义一个tail指针,用于记录newhead链表中的最后一个元素的地址。(所以每次尾插之后tail指针要进行更新)newhead保持不变,永远指向第一个节点。所以共要,创建四个结构体指针:cur、newhead、next、tail。cur指针用于遍历原链表,newhead用于记录新链表的头,最后函数的返回值就用newhead进行返回,next指针用于记录cur指针的下一个位置,方便进行尾插操作,tail指针用于记录newhead链表中的最后一个元素,并且每一次的尾插之后都要进行更新。


思路二:


直接使用cur指针和prev指针遍历原链表,cur指针从原链表的头开始遍历,prev用于记录cur的上一个节点的地址。假如cur指向的节点的值为val,先让prev和cur节点的next连接起来。接着释放cur指向的节点。(但是假如cur一开始指向head时,该节点的值也恰好为val,则此时要进行头删操作,并且释放之后的节点无效了,需要更新head。)


思路一代码:


struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode* cur = head;
    struct ListNode* next = head;
    struct ListNode* newhead = NULL;
    struct ListNode* tail = newhead;
    while(cur)
    {
        //满足删除条件
        if(cur ->val != val)
        {
            //假如newnode是空
            if(newhead== NULL)
            {
                next = cur->next;
                newhead = cur;
                tail = newhead;
                cur = next;
            }
            //newnode不是空
            else
            {
                next = cur->next;
                tail->next = cur;
                tail = tail->next;
                cur = next;
            }
        }
        //不满足删除条件
        else
        {
            next = cur->next;
            free(cur);
            cur = next;
        }
    }
        if(tail!=NULL)
        tail->next = NULL;
        return newhead;
}

思路二代码:


    struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode* prev=NULL;
    struct ListNode* cur = head;
    while(cur)
    {
        //节点的值满足删除条件
        if(cur->val == val)
        {
            //当删除的是头节点
            if(cur == head)
            {
                head = cur->next;
                free(cur);
                cur = head;
            }
            //当删除的不是头节点
            else
            {
                prev->next = cur->next;
                free(cur);
                cur = prev->next;
            }
        }
        //节点的值不满足删除条件
        else//向后走
        {
            prev = cur;
            cur=cur->next;
        }
    }
    return head;
}

注意:以下都是针对思路一的讲解:


图解:


在代码的初始状态是如下图所示的:此时的next和cur都指向head,也就是原链表中的第一个元素。newhead和tail为空指针时,要进行特判,记录cur的下一个位置之后,要先让newhead指向cur,同时tail指针也向后移动了一步指向cur,完成了更新。


58a4abb0e9bde9e55262cb4b198dc440_2d6821af19b34fd3877e7a11d068d0dd.png


当来到下图所示的常规情况时,此时的tail和newhead都不为空,newhead不能动,记录cur的next之后,直接改变tail的next并且更新tail即可。


25f0399740670c0f34539a7da6465de1_a77316a3d2664249b9c5c8f5c87dfbf9.png


当代码进行到如下图所示时,此时cur为空指针,while循环结束,按常理来讲就应该要返回newhead了。(单链表的最后一个节点的next指针的值必须是NULL)但是,此时的的tail的next指针仍然是指向6所在的节点的,并且该节点虽然被释放了,但是值就会变成随机值,并不一定是NULL,所以在返回newhead之前,要将tail的next置为空指针。


9bb47382ce0b4d2c12dd1efdeb83aa8a_823df24cac5845ef9b66c2a5b2495570.png


注意:当测试用例使用空链表测试时,cur的值也为NULL,while循环并没有进入。也就说明tail的值一直都是NULL并没有被改变,如果此时仍然使用tail->next = NULL;强行置空就会出现空指针访问错误。所以此处需要进行特判。


完结


本题的全部分析就到这里啦,若有不足,欢迎评论区指正,下期见!


相关文章
|
1月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
34 1
|
3月前
|
程序员
【刷题记录】移除链表元素
【刷题记录】移除链表元素
01_移除链表元素
01_移除链表元素
|
1月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
29 0
|
3月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
3月前
|
存储 C语言
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
|
4月前
【数据结构OJ题】移除链表元素
力扣题目——移除链表元素
43 2
【数据结构OJ题】移除链表元素
|
3月前
|
Python
【Leetcode刷题Python】203.移除链表元素
文章提供了三种删除链表中特定值节点的方法:迭代法、虚拟节点迭代删除法和递归法,并给出了相应的Python实现代码。
24 0
|
4月前
链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
32 0
|
5月前
|
算法
【数据结构与算法 刷题系列】移除链表元素
【数据结构与算法 刷题系列】移除链表元素