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

题目描述

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

在这里插入图片描述

思路一

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

一、考虑常见情况
要移除某一结点,也就是让该结点的前一个结点指向待移除结点的后一个结点,然后将待移除结点释放即可。我们可以定义3个指针变量:prev,cur,next 。

prev:记录待排查结点的前一个结点位置(previous)。
cur:记录当前正在排查的结点位置(current)。
next:记录待排查结点的后一个结点(next)。
在这里插入图片描述
当cur指针指向的结点并非待移除的结点时,3个结点依次向后移动。
在这里插入图片描述
当cur指针指向待移除的结点时,我们首先让prev指针指向的结点指向next,然后将cur指针指向的结点释放掉,并将next指针赋值给cur指针,next指针再后移。
在这里插入图片描述
如此进行下去,直到链表遍历完毕,那么值为val的结点也就删除了。

二、考虑特殊情况
常见情况的分析往往只能解决问题的一般情况,并不能解决问题的极端情况。要真正解决问题,我们需要考虑到问题的极端情况。例如,当待移除的结点是第一个结点或是最后一个结点的情况,当链表为空的情况。
1.当链表的第一个结点为待移除的结点时
在这里插入图片描述
这时我们需要先将头指针指向next,然后释放cur指向的结点,并将next指针赋值给cur指针,next指针再后移。
在这里插入图片描述
2.当链表的最后一个结点为待移除的结点时
当排查到最后一个结点时,cur指向最后一个结点,next指针指向该结点指向的位置,即NULL。
在这里插入图片描述
我们用上面常规情况的方法对其进行分析,发现常规情况的思路适用于这种特殊情况。并且发现遍历的终止条件,就是当cur为NULL的时候遍历停止。
在这里插入图片描述
3.当传入链表为空时
我们可以发现,若传入的链表为空链表(NULL),cur指针的值一开始就为空,而我们遍历的终止条件就是当cur为NULL时停止遍历,所以当传入链表为空时,直接执行到函数末尾,即返回头指针(NULL)。

代码实现

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;//返回新的头指针
}

思路二

我们可能觉得思路一的代码比较复杂,当我们要移除某一个结点时,还需要判断该结点是否为第一个结点,那么有没有什么办法可以不用进行这一步操作呢?
回答是肯定的。办法就是在传入的链表前面强行加上一个头结点,并让链表原来的头指针指向该头结点,这样我们就不用判断待移除的结点是否为第一个结点了(因为现在第一个结点是头结点)。
在这里插入图片描述
在加了头结点后,我们就只需要根据常见情况的逻辑进行代码的编写即可。但是有一点不能忘记,就是在遍历完链表后要将头结点指向的位置(即第一个结点的位置)赋值给头指针,并将头结点释放掉,最后才能返回头指针。
在这里插入图片描述

代码实现

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* cur = guard->next;//cur指针指向原链表第一个结点
	struct ListNode* prev = guard;//prev指针指向头结点
	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;//返回新的头指针
}
  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 26
    评论
以下是移除链表元素的Python代码: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def removeElements(head: ListNode, val: int) -> ListNode: # 处理头部节点为要删除元素的情况 while head is not None and head.val == val: head = head.next # 处理链表间节点为要删除元素的情况 if head is not None: node = head while node.next is not None: if node.next.val == val: node.next = node.next.next else: node = node.next return head ``` 这里定义了一个ListNode类表示链表节点,其val表示节点的值,next表示指向下一个节点的指针。removeElements函数的第一个参数head表示链表的头节点,第二个参数val表示要删除元素值。函数的返回值是移除后的链表头节点。 函数的实现分为两步: 1. 处理头部节点为要删除元素的情况,即如果头部节点的值等于要删除元素值,则将头部节点指向下一个节点,直到头部节点的值不等于要删除元素值。 2. 处理链表间节点为要删除元素的情况,即从头节点开始遍历链表,如果当前节点的下一个节点的值等于要删除元素值,则将当前节点的next指针指向下一个节点的next指针,即跳过当前节点的下一个节点;否则,将当前节点指向下一个节点。遍历完成后,返回链表的头节点。 注意,这里的实现并没有考虑链表为空的情况,需要在调用函数前进行判断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021dragon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值