代码随想录-013-LeetCode剑指Offer203.移除链表元素

前言

“代码随想录”刷题记录。总结笔记均会放在“算法刷题-代码随想录”该专栏下,以下为原文的链接。
代码随想录此题链接

题目

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

示例 1:

输入: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

1. 移除链表

思路

分两种,一种是含有虚拟头结点,一种不含有虚拟头节点,因为含有虚拟头节点的处理更加通用,故只介绍含有虚拟头节点的方式(卡哥对这两种都有详细解释)。

需要的变量:

  1. 定义链表结构的结构体struct
  2. 虚拟头节点 dummyHead指针
  3. 当前节点 cur指针
  4. 指向删除节点的temp指针

2. 本题思路分析:

  1. 每次通过当前节点去检查下一个节点的值是否符合移除的条件(即cur->next->val是否等于规定值val),而不是去检查当前节点是否满足移除条件(因为要通过上一个节点,移除下一个节点(上一个节点next指向下下一个节点,相当于从链表中移除了下一个节点,不过还要在内存中删除节点所占用的空间))。
  2. 若不满足条件,则cur指针后移一位(cur=cur->next)
  3. 跳出循环后,head头指针需要指向虚拟头指针的next指针,如果head头指针指向的节点是需要删除的,那么在节点被删除后,head头指针指向的就是释放后的节点(head节点变成了未定义的指针(虽然还指在原始的空间地址上,但是该地址已经被释放不具备存储功能,变成了垃圾空间,指向这样垃圾地址的指针不安全,这样的指针被称为野指针)),在力扣上返回被释放的指针,会报heap-use-after-free这样的错,并且最后也需要删除虚拟头节点,避免占用多余内存空间。

3. 算法实现

  • 代码:
#include<stdio.h>
#include<vector>
using namespace std;
struct ListNode{
	int val;
	ListNode* next;
	ListNode* () : val(0),next(NULL){}
	ListNode* (int x):val(x),next(NULL){}
	ListNode* (int x,ListNode* next):val(x),next(next){}
}
ListNode* removeElements(ListNode* head, int val) {
//虚拟头节点
	ListNode* dummyHead = new ListNode(0);
	dummyHead -> next = head;
	ListNode* cur = dummyHead;
	ListNode* temp = new ListNode(0);
	while(cur != NULL && cur -> next != NULL){
		//判断此节点不为最后一个节点(最后一个节点是虚拟头节点),并且不为空节点
		if(cur -> next -> val == val){
			//删除next指针的节点
			temp = cur -> next;
			cur -> next = cur -> next -> next;
			delete temp;
		}else{
			//cur指针后移一位
			cur = cur -> next;
		}
	}
	//此时所有该被删除的节点已经全部被删除
	head = dummyHead -> next;
	delete dummyHead;
    return head;
}

4. 算法分析

n为数组长度
时间复杂度:O(n)
空间复杂度:O(1)

5. 算法坑点

  • 1.避免产生野指针:设置虚拟节点的解法中,在删除了所有应该删除的节点后,记得要把head头结点赋值为dummyHead虚拟节点的后一个节点,并且删除dummyHead虚拟头节点。(因为head有可能会被释放,指向了一个释放节点,成为一个野指针)

野指针的产生和危害

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值