《算法通关村第一关——链表经典问题之删除链表元素笔记》

文章介绍了三种在链表中删除结点的方法:一是删除包含特定数据的结点,通过创建虚拟表头,遍历链表找到目标结点并断开连接;二是删除倒数第n个结点,先获取链表长度,再定位到目标位置删除;三是删除有序链表中的重复结点,分保留一个重复和全部删除两种情况处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方式一:删除特定结点

示例:

输入:head = [1,2,6,3,4,5,6],data  = 6

输出:[1,2,3,4,5]

说明:删除节点node时,必须知道前驱pre节点和后继next结点,然后让pre.nextNode=node.nextNode,这样node就脱离了链表,会在某个时刻被gc回收掉。

思路:1.创建一个虚拟表头node,使其nextNode指向headNode,再创建一个新的结点:Node cur = node。

           2.开始循环链表寻找特定结点,使用cur.nextNode.data来判断是否为特定节点。

           3.如果找到目标元素,使用cur.nextNode=cur.nextNode.nextNode来删除。

           4.如果不是目标元素,使用cur=cur.nextNode。

           5.注意返回值应该为:node.next。

具体实现的代码封装在方法removeNode()中,如下:

    //移除指定数据的节点,data表示要删除结点的数据,headNode为头结点
	private static Node removeNode(int data,Node headNode) {
		//创建一个虚拟节点node,指向headNode
		Node node =new Node(0);
		node.nextNode = headNode;
		Node curNode = node;
		while(curNode.nextNode!=null) {
			if(curNode.nextNode.data == data) {
				curNode.nextNode = curNode.nextNode.nextNode;
			}else {
				curNode = curNode.nextNode;
			}
		}
		return node.nextNode;
	}

方式二:删除倒数第n个结点

示例:

输入:head=[1,2,3,4,5],n=2

输出:[1,2,3,5]

思路:先遍历一遍链表获得链表的长度L,然后再次遍历删除位置为L-n+1的结点 。

          1.创建一个虚拟表头node,使其nextNode指向headNode,再创建一个新的结点:Node curNode = node。 

           2.开始循环链表将curNode指向第L-n+1个结点的前驱结点,然后使用curNode.next=curNode.nextNode.nextNode删除结点。

具体代码入下:

//删除倒数第n个结点
	private static Node removeEndNode(int n,Node headNode) {
		Node node = new Node(0);
		node.nextNode = headNode;
		Node curNode = node;
		int m = linkedListLength(headNode);
		//删除第i个结点
		int i = m - n + 1;
		for(int k=1;k<i;k++) {
			curNode=curNode.nextNode;
		}
		curNode.nextNode = curNode.nextNode.nextNode;
		return node.nextNode;
	}
	//遍历链表获得链表的总长度L
	private static int linkedListLength(Node headNode) {
		int m=1;
		Node curNode = headNode;
		while(curNode.nextNode != null) {
			curNode=curNode.nextNode;
			m++;
		}
		return m;
	}

方式三:删除重复元素

(1)重复元素保留一个

前提:链表为升序。

示例:

输入:head=[1,1,2,3,3]

输出:[1,2,3]

思路: 由于链表已经是排序好的,因此重复的元素是连续的,对链表进行遍历,查询重复即可删除重复的元素。

具体代码如下:

//删除重复的结点,链表为有序
	private static Node deleteDuplicates(Node headNode) {
		Node node = headNode;
		if(headNode == null) {
			return headNode;
		}
		while(node.nextNode != null) {
			if(node.data == node.nextNode.data) {
				node.nextNode = node.nextNode.nextNode;
			}else {
				node = node.nextNode;
			}
		}
		return headNode;
	}

(2)重复元素都不要

前提:链表为有序。

示例:

输入:head=[1,2,3,3,4,4,5]

输出:[1,2,5]

思路:链表直接对curNode.nextNode以及curNode.nextNode.nextNode两个node进行比较就行了,这里需要注意两个node可能为空,需要判断。

具体代码如下所示:

        //删除重复的结点全部删除,链表为有序
		private static Node deleteDuplicates(Node headNode) {
			Node node = new Node(0);
			node.nextNode = headNode;
			Node curNode = node;
			if(headNode == null) {
				return headNode;
			}
			while(curNode.nextNode != null && curNode.nextNode.nextNode!=null) {
				if(curNode.nextNode.data == curNode.nextNode.nextNode.data) {
					int x = curNode.nextNode.data;
					while(curNode.nextNode != null && curNode.nextNode.data==x) {
						curNode.nextNode = curNode.nextNode.nextNode;
					}
				}else {
					curNode = curNode.nextNode;
				}
			}
			return node.nextNode;
		}

准备蓝桥杯算法竞赛是一个系统性的工程,涉及到对数据结构算法知识的深入理解以及实践应用。为了高效地利用LeetCode资源库,建议采取以下策略: 参考资源链接:[蓝桥杯备战:全面LeeCode算法学习资源汇总](https://wenku.youkuaiyun.com/doc/8apziue7z7?spm=1055.2569.3001.10343) 首先,结合《蓝桥杯备战:全面LeeCode算法学习资源汇总》一书,对蓝桥杯竞赛的历年真题和LeetCode题库中的题目进行分类。按照数据结构的类型(如数组、链表、栈、队列、树、图等)和算法主题(如搜索、排序、动态规划、贪心算法等)进行归纳总结。 其次,制定一个分阶段的学习计划。初期阶段,建议从简单的数组和链表题目入手,逐步过渡到中等难度的题目,如栈和队列的应用,最终挑战树和图等复杂数据结构问题。对于算法主题,可以先从搜索和排序开始,逐渐深入到动态规划和贪心算法等高级主题。 在进行每一种数据结构算法主题的学习时,都应该遵循以下步骤: 1. 学习理论知识:阅读相关章节,理解各种数据结构算法的原理。 2. 观看视频教程:例如,参考《清华大佬LeetCode教程》,了解解题思路和代码实现。 3. 在LeetCode上实践:在官方题库中找到相应类别的题目进行编码练习。 4. 分析和总结:完成题目后,分析解题过程中的问题和漏洞,并做笔记总结。 5. 复习与拓展:定期复习笔记和完成的题目,同时尝试解决更高难度或不同类型的题目。 此外,建立一个合理的时间管理策略也是至关重要的。可以设定每周的学习目标,并跟踪进度。建议采用番茄工作法等时间管理技巧来提高学习效率。 最后,建议加入开源项目如程序员充电站/LeetCode-Py,参与其中的学习和讨论,可以有助于提升实战经验并获得新的解题思路。同时,参考算法关手册和LeetCode算法笔记,可以加深对算法理论的理解,并掌握更多解题技巧。 过上述步骤和策略,结合《蓝桥杯备战:全面LeeCode算法学习资源汇总》一书提供的资源,相信你能够在蓝桥杯算法竞赛中取得优异成绩。 参考资源链接:[蓝桥杯备战:全面LeeCode算法学习资源汇总](https://wenku.youkuaiyun.com/doc/8apziue7z7?spm=1055.2569.3001.10343)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值