剑指offer之面试题18:删除链表的节点

删除链表的节点

1、题目

给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。

输入参数:单向链表的头指针pHead,节点指针pToBeDeleted

输出结果:无

2、解题

这道题的关键在于如何在时间复杂度为O(1)的情况下删除指定节点

因此,我们可以想到覆盖的方法:先获得要删除节点的下一节点,将下一节点的值赋值给删除节点,再将删除节点的指针指向下下个节点,最后删除下一节点即可,通过后面覆盖前面的方式进行删除。

这道题的难度在于对删除节点不同情况的划分

需要划分为三种情况:

  • 删除的节点非尾结点(隐含了存在两个或以上节点的前提),覆盖删除
  • 删除的节点为尾结点
    • 若链表中只有一个节点,即头节点等于尾结点,直接删除即可
    • 若链表中有多个节点,需要找到尾结点的前一个节点,再进行删除操作
3、代码
void DeleteNode(ListNode** pHead, ListNode* pToBeDeleted) {
	//鲁棒性检查
	if (!pHead || !pToBeDeleted)
		return;

	//首先判断要删除的节点是否是尾结点
	if (pToBeDeleted->m_pNext != nullptr) {
		ListNode* pNext = pToBeDeleted->m_pNext;
		//进行覆盖
		pToBeDeleted->m_nValue = pNext->m_nValue;
		pToBeDeleted->m_pNext = pNext->m_pNext;
		//删除
		delete pNext;
		pNext = nullptr;
	}
	//如果要删除的是尾结点
	else if (pToBeDeleted == *pHead) {
		//当只有一个节点时,即尾结点和头节点重合时
		delete pToBeDeleted;
		pToBeDeleted = nullptr;
		*pHead = nullptr;
	}
	else {
		//当链表中有多个节点时,需要先找到尾结点的前一个节点
		ListNode* pNode = *pHead;
		while (pNode->m_pNext != pToBeDeleted) {
			pNode = pNode->m_pNext;
		}
		pNode->m_pNext = nullptr;
		delete pToBeDeleted;
		pToBeDeleted = nullptr;
	}

}
4、注意点
  • 之所以删除尾结点时,要找到其前一个节点而不是直接删除节点,是为了防止出现空指针异常
  • 注意鲁棒性的检查
  • 链表中只有一个节点时,在删除节点后要将头指针置空
5、代码的可行性

上述代码是基于一个假设:要删除的节点的确在链表中。我们需要使用O(n)的时间才能判断节点是否在链表中,但又受到O(1)时间的限制,因此我们不得不把确保节点在链表中的责任交给函数DeleteNode的调用者。在面试的时候,我们可以和面试官探讨这个假设,把问题考虑得更加全面。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值