拿捏链表(一)-----------移除链表元素

简介: 拿捏链表(一)-----------移除链表元素

题目描述

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

思路一:

要移除链表中值为val的节点,我们肯定是要将链表遍历一遍的,关键是我们在遍历中如何操作是一个问题。所有,我们考虑问题的时候,可以先考虑比较常见的情况,再考虑特殊情况。

1.考虑常见情况

要移除某一节点,也就是让该节点的前一个节点指向待移除节点的后一个节点,然后将待移除节点释放即可。这里呢,我们可以定义三个指针变量:prev,cur,next.

prev(previous):记录待排查节点的前一个节点的位置。

cur(current):记录当前正在排查的节点位置。

next(next):记录待排查节点的后一个节点。

当cur指针指向的节点并非待移除的节点时,3个节点依次向后移动。

当cur指针指向待移除的节点时,我们首先让Prev指针指向的节点指向next,然后把cur指针指向的节点释放掉,并将next指针赋值给cur指针,next指针向后移动。

如此进行下去,直到链表遍历完毕,值val的节点也就删除完了。

2.考虑特殊情况

常见的请款的分析往往只能解决问题的一般情况,并不能解决问题的极端情况。要真正的解决问题,我们需要考虑到的问题的极端情况。如,当待移除的节点时第一个节点或者是最后一个节点的情况,当链表为空的情况。

2.1当链表的第一个节点为待移除的节点时:

这时我们需要先将头指针指向Next,然后释放掉cur所指向的节点,并将next指针赋值给cue指针,next再后移。

2.2当链表的最后一个节点为待移除的节点时:

当排查到最后一个节点时,cur指向最后一个节点,next指针指向该节点的位置,即NULL.

我们上面常规情况的方法对其分析,发现常规情况的思路适用于这种特殊情况,并且发现遍历的终止条件,就是当cur为NULL时遍历停止。

2.3当传入的链表为空时:

我们会发现,如果传来的是空链表,cur指针的值一开始就为空,而我们遍历的终止条件就是当cur为NULL时停止遍历,所以,如果传来的是空链表,直接执行到函数末尾,即返回头指针。(NULL)

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode 
 * {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val)
{
   struct ListNode*prev=NULL;//记录待排查节点的前一个节点位置
   struct ListNode*cur=head;//记录当前正在排查的节点位置
   while(cur!=NULL)//当cur为空时,循环停止
   {
       if(cur->val==val)//当前排查的节点时待移除的节点
       {
            struct ListNode*next=cur->next;//记录待排查节点的后一个节点位置
            if(cur==head)//带移除节点是链表的第一个节点
            {
                head=next;//头指针指向next
                free(cur);//释放掉第一个节点
                cur=next;//将Next指针赋值给cur指针
            }
            else //带移除的节点不是链表的第一个节点
            {
                prev->next=next;//prev指针指向的节点指向next
                free(cur);//将cur指针指向的节点释放掉
                cur=next;//将next指针赋值给cur指针
            }
       }
       else//当前排查的节点不是待移除的节点
       {
           prev=cur;//指针后移
           cur=cur->next;//指针后移
       }
   }
     return head;//返回新的头指针
}

思路二:

思路一可能过于麻烦,当我们要移除某一个节点时,还需要判断该节点是否为第一个节点,那么有没有什么办法可以不进行这个操作呢?

回答是肯定的。新的解决办法就是在传入的链表前面强行加上一个头节点,并让链表原来的头指针指向该头节点,这样我们就不用判断待移除的节点是否为第一个节点了(因为现在第一个节点就是头节点)。

在加了头节点后,我们就只需要根据常见情况的逻辑进行代码编写。但是有一点需要注意的是,遍历完链表后要将头节点指向的位置(即第一个节点的位置)赋值给头指针,并将头节点释放掉,最后才能返回头指针。

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode 
 * {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val)
{
   struct ListNode*guard=(struct ListNode*)malloc(sizeof(struct ListNode));//申请一个头节点,返回其地址
   guard->next=head;//让头节点指向链表的第一个节点
   struct ListNode*prev=guard;//prev指针指向头节点
   struct ListNode*cur=guard->next;//cur指针指向原链表的第一个节点
   while(cur!=NULL)//当cur为空时,循环停止
   {
       if(cur->val==val)//当前排查的节点时待移除的节点
       {
                struct ListNode*next=cur->next;//记录待排查节点的后一个节点位置
                prev->next=next;//prev指针指向的节点指向next
                free(cur);//将cur指针指向的节点释放掉
                cur=next;//将next指针赋值给cur指针
       }
       else//当前排查的节点不是待移除的节点
       {
           prev=cur;//指针后移
           cur=cur->next;//指针后移
       }
   }
    head=guard->next;//将头节点指向的位置赋值给头指针,使头指针指向链表第一个节点
    free(guard);//释放头节点
    guard=NULL;//及时置空
     return head;//返回新的头指针
}

解题结果如下:

文章到这里就结束了,有更好的思路或问题的,欢迎留言评论区。

下期预告:拿捏链表(二)-------- 反转链表

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