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

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

方式一:删除特定结点

示例:

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值