在O(1)时间内删除链表节点

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

struct ListNode

{

int    m_nValue;

ListNode* m_pNext;

};

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted);

算法思路:

一般我们是从头节点开始遍历,知道找到要删除的节点的前面一个节点,但是时间复杂度为O(n)

改进思路:找到要删除的节点pDeleteNode的下一个节点pNext,把下一个节点的值(pNext->m_nValue)

赋给要删除的节点(PDeleteNode->m_nValue),再把要删除的节点指向下一个节点的下一个节点:(pDelete->m_pNext = pNext->m_pNext)

然后再把pNext节点删除,pNext = NULL;

代码:

// DeleteNodeInList.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

/*
算法思路:
一般我们是从头节点开始遍历,知道找到要删除的节点的前面一个节点,但是时间复杂度为O(n)
改进思路:找到要删除的节点pDeleteNode的下一个节点pNext,把下一个节点的值(pNext->m_nValue)
赋给要删除的节点(PDeleteNode->m_nValue),再把要删除的节点指向下一个节点的下一个节点:(pDelete->m_pNext = pNext->m_pNext)
然后再把pNext节点删除,pNext = NULL;

*/

struct ListNode
{
	int		  m_nValue;
	ListNode* m_pNext;
};

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
	if (!pListHead || !pToBeDeleted)
	{
		return;
	}
	if (pToBeDeleted->m_pNext != NULL)//删除的节点不是尾巴节点
	{
		ListNode* p = pToBeDeleted->m_pNext;
		pToBeDeleted->m_nValue = p->m_nValue;
		pToBeDeleted->m_pNext = p->m_pNext;

		delete p;
		p = NULL;
	}
	else if (*pListHead == pToBeDeleted)//链表只有一个节点,删除头节点也是尾巴节点
	{
		delete pToBeDeleted;
		pToBeDeleted = NULL;
		*pListHead  = NULL;
	}
	else//链表中有多个节点,删除尾巴节点
	{
		ListNode* pNode = *pListHead;
		while (pNode->m_pNext != pToBeDeleted)
		{
			pNode = pNode->m_pNext;
		}
		pNode->m_pNext = pToBeDeleted->m_pNext;
		delete pToBeDeleted;
		pToBeDeleted = NULL;
	}

}

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

*/

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}

对于n-1个非尾巴节点而言,我们可以在O(1)的时间把下一个节点的内存复制覆盖要删除的节点,并删除下一个节点;

对于尾巴节点而言,由于仍然需要顺序查找,时间复杂度是O(n).因此总的平均时间复杂度是[(n-1)*O(1)+O(n)]/n,

因此平均时间复杂度是O(1);

时间: 2024-10-13 10:46:06

在O(1)时间内删除链表节点的相关文章

在O(1)时间内删除链表节点(剑指offer_18.1)

解题思路 如果该节点不是尾结点,那么可以直接将下一个节点的值赋给该节点,然后该节点指向下下个节点,再删除下一个节点,时间复杂度为O(1). 否则,就需要先遍历链表,找到节点的前一个节点,然后让前一个节点指向null,时间复杂度为O(N).综上,如果进行N次操作,那么大约需要操作节点的次数为N-1+N = 2N - 1,其中N-1表示N-1个不是尾结点的每个节点以O(1)时间复杂度操作该节点的总次数,N表示1个尾结点以O(N)的时间复杂度操作节点的总次数.(2N-1)/N ~ 2,因此该算法的平均

面试题18:删除链表节点

18.1 在 O(1) 时间内删除链表节点 <?php header("content-type:text/html;charset=utf-8"); /* * 在 O(1) 时间内删除链表节点. P119 */ class ListNode{ var $val; var $next = NULL; function __construct($x){ $this->val = $x; } } function deleteNode($head,$deleteNode){ i

经典算法学习——在O(1)时间删除链表节点

这道算法题同样是剑指Offer中的一道题,题目描述为:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点.其实我们知道,想要在单向链表中找到某个节点并删除它,复杂度为O(n),因为必须从头遍历才能找到它(最重要的是因为要找到它的前一个节点.)所以想要O(1)完成,必须想其他的方法. 目前重要的一个信息就是已经有一个节点指针指向当前要删除的节点.这就比较好办了.我们可以非常方便的找到它的后继节点,然后把后继节点的值赋值给当前要删除的节点,然后再去删除那个后继节点.这样,我们

【编程题目】在 O(1)时间内删除链表结点

60.在 O(1)时间内删除链表结点(链表.算法).题目:给定链表的头指针和一个结点指针,在 O(1)时间删除该结点.链表结点的定义如下:struct ListNode{int m_nKey;ListNode* m_pNext;};函数的声明如下:void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted); 思路:把当前结点的下一个结点的内容复制到当前结点,删除下一结点即可. 注意,链表中只有一个结点时在题目给定的函数声明下无法删除,

lintcode 容易题:Delete Node in the Middle of Singly Linked List 在O(1)时间复杂度删除链表节点

题目: 在O(1)时间复杂度删除链表节点 给定一个单链表中的表头和一个等待被删除的节点(非表头或表尾).请在在O(1)时间复杂度删除该链表节点.并在删除该节点后,返回表头. 样例 给定 1->2->3->4,和节点 3,返回 1->2->4. 解题: 方法好贱,先把要删除节点后面一个节点的值赋给删除节点,这样需要删除节点就删除了,再把删除节点指向删除节点后面节点的节点 就像这样: node.val = node.next.val; node.next = node.next.

LeetCode之“链表”:在O(1)时间删除链表节点

下边讨论暂不包括尾节点. 一般来说,我们要删除链表中的一个节点是需要知道其上一节点的.但我们真的需要吗? 其实我们可以将待删节点的下一节点的值和指向的下一节点赋予待删节点,然后删除待删节点的下一节点.具体示例程序如下: 1 //O(1)时间删除链表节点,从无头单链表中删除节点 2 void deleteRandomNode(Node *cur) 3 { 4 assert(cur != NULL); 5 assert(cur->next != NULL); //不能是尾节点 6 Node* pNe

关于递归删除链表节点为什么不会断链问题解释

问题的由来:    当你第一次实现用递归实现链表删除功能的时候,是否有一丝丝的考虑过.这个问题呢?为什么对于非递归版本的删除必须要知道当前要删除节点的前驱,而需要对其前驱节点的next域指针进行修改.而递归删除却不需要呢?难道这样不会造成链表的断链吗? 好了.我们开始抽象出我们今天要解决的问题. 问题一: 递归实现链表节点的删除和非递归删除的区别是什么? 问题二: 为什么在使用递归删除的时候链表不会断链? 先给个代码,好根据代码模拟,不会空想. 函数的递归模型: 终止条件: f(L,x) = 不

剑指offer---以O(1)时间删除链表节点

问题:删除链表节点 要求:以O(1)时间 对于删除指定索引的链表元素大家都很熟悉,思路一般是从头遍历链表直到指定索引位置删除元素,然后维护一下指针即可,时间复杂度O(n).代码如下: 1 // 删除position位置的数据,并返回 2 int List::erasePosition(int position){ 3 if(position<0 || position>(List::size()-1)){ 4 cout<<"position error, please c

剑指Offer之在O(1)时间删除链表节点

题目描述 给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点. 解题思路 在单向链表中删除一个节点,最常规的做法无疑是从链表的头结点开始,顺序的遍历查找要删除的节点,并在链表中删除该节点.这种思路由于需要顺序查找,时间复杂度自然就是$O(n)$了. 之所以需要从头开始查找,是因为我们需要得到将删除的节点的前面一个节点.在单向链表中,节点中没有指向前一个节点的指针,所以只好从链表的头结点开始顺序查找.那是不是一定需要得到被删除的节点的前一个节点呢?答案是否定的.我们可以很方便