剑指offer面试题13——在O(1)删除链表节点

题目要求:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。其中,链表节点与函数的定义如下:

package offer;

public class ListNode
{
	int val;
	ListNode next;
	ListNode(int x)
	{
		val=x;
	}
}

分析:在单向链表中删除一个节点,最常规的做法无疑是从链表的头结点开始,顺序遍历查找要删除的节点,并在链表中删除该节点,在下图(1)中,我们想删除链表i,可以从链表的头节点a开始顺序遍历,发现节点h的next节点指向要删除的节点i,于是我们可以把节点h的next指向i的下一个节点,即节点j,指针调整之后,我们就可以安全的删除节点i并保证链表没有断开(如(2)所示),这个思路由于需要顺序查找,时间复杂度自然就是O(1)




继续分析:那怎样才能实现时间复杂度是O(1)的算法呢,我们发现要删除节点i,可以先把i的下一节点j的内容复制到i上,然后把i的指针指向节点j的下一个节点。此时再删除节点j,其效果刚好是把节点i给删除了(如图(3)所示)

注意:如果链表中只有一个节点,而我们又要删除链表的头节点(也是尾节点),此时我们在删除节点之后,还需要把链表的头节点设置为null

代码如下:

package offer;

public class delete_SelectedNode
{
	public void DeleteNode(ListNode head,ListNode pToBeDeleted)
	{
		if (head==null||pToBeDeleted==null)
		{
			return;
		}
		//要删除的节点不是尾节点
		if (pToBeDeleted.next!=null)
		{
			//pNext指向pToBeDeleted下一节点
			ListNode pNext=pToBeDeleted.next;
			//复制pNext到pToBeDeleted
			pToBeDeleted.val=pNext.val;
			//删除pNext,等效删除pToBeDeleted,等效指针操作
			pToBeDeleted.next=pNext.next;
			pNext=null;
		}
		//当删除为头指针时
		else if (pToBeDeleted==head)
		{
			pToBeDeleted=null;
			head=null;
		}
		//当链表有多个节点,删除尾节点
		else 
		{
			ListNode pNode=head;
			while (pNode.next!=pToBeDeleted)
			{
				pNode=pNode.next;
			}
			pNode.next=null;
			pToBeDeleted=null;
			
		}
	}
}

时间复杂度分析:对于n-1个非尾节点而言,我们可以再O(1)时把下一个节点的内存复制覆盖要删除的节点,并删除下一个节点,对于尾节点而言,由于仍然需要顺序查找,时间复杂度是O(n),因此中的平均时间复杂度是[(n-1)*O(1)+O(n)]/n,结果还是O(1),符合题意



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值