【36】在O(1)的时间删除链表结点

题目:给定一个单向链表(只有指向下一个结点的指针)的头结点和某一个结点的指针,求怎样在O(1)的时间删除这个给定结点。

分析:

1.  最朴素的算法是从头结点开始搜索到给定结点前一个结点,然后把结点删除。这种方法的时间复杂度为0(n),所以不能在O(1)的时间内删除该结点

2. 要求在O(1)的时间内删除某个结点,肯定是利用单向链表的性质。给定单向链表只有指向下一个结点的指针,我们无法得到前面一个结点的指针。所以我们可以考虑换个思路。

    (1)假设要删除的链表如下

    (2)因为给定结点2的指针,那么通过下一个结点指针可以得到结点3的指针。所以实际上删除结点2等价于把结点3复制一份到结点2中,然后删除结点3,如下图

   (3)所以实际上,就是把给定结点的下一个结点复制给当前结点然后删除下一个结点。这样就可以在O(1)的时间内删除某一个结点

注意:

1. 由于涉及到下一个结点,所以要考虑多种情况

  (1)删除结点是头结点

  (2)删除结点在中间,既不是头结点也不是尾结点

  (3)删除结点是尾结点

2. 对于这些情况要分类讨论 

   总的分成两类,删除结点的下一个结点是否为空和不空

   (1)如果删除结点的下一个结点为空,说明删除结点是尾结点。则这个时候要采用从头遍历,因为没有办法把空结点复制给当前结点,这个是必须O(n)枚举。注意链表有且仅有一个结点并删除尾结点情况

   (2)如果删除结点的下一个结点不为空,则直接把下一个结点复制给当前结点,然后删除下一个结点即可

代码:

//链表结点
struct ListNode{
    int value;
	ListNode *nextNode;
};

//删除一个结点,涉及到修改指针传递指针的指针
void DeleteNode(ListNode **headNode, ListNode **deleteNode){
    //不合法数据
	if((*headNode) == NULL || (*deleteNode) == NULL){
	    return;
    }
    //删除结点
	ListNode *deleteNodeNextNode = (*deleteNode)->nextNode;
	//如果下一个结点是为空,直接删除该点
	if(deleteNodeNextNode == NULL){
        //遍历删除
		ListNode *tmpNode = (*headNode);
		while((tmpNode != NULL) && (tmpNode->nextNode != (*deleteNode))){
		      tmpNode = tmpNode->nextNode;
	    }
	    //如果当前链表有且只有一个点则tmpNode变成NULL
	    if(tmpNode != NULL){
		    tmpNode->nextNode = NULL;
		}
		delete (*deleteNode);
		(*deleteNode) = NULL;
    }
    else{
        //把下一个结点值复制给当前结点
		(*deleteNode)->value = deleteNodeNextNode->value;
        (*deleteNode)->nextNode = deleteNodeNextNode->nextNode;
         //删除下一个结点
		 delete deleteNodeNextNode;
		 deleteNodeNextNode = NULL;
    }
} 
时间: 2024-10-12 17:36:40

【36】在O(1)的时间删除链表结点的相关文章

[经典面试题]在O(1)时间删除链表结点

[题目] 给定链表的头指针和一个结点指针,在O(1)时间删除该结点.链表结点的定义如下: struct ListNode {     int        value;     struct ListNode*  next; }; 函数的声明如下: void DeleteNode(ListNode* head,ListNode* node); [思路] 这是一道广为流传的Google面试题,能有效考察我们的编程基本功,还能考察我们的反应速度,更重要的是,还能考察我们对时间复杂度的理解. 在链表中

时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法

有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和做法. 如图所示,删除结点 i,那么只需找到 i 的前驱 h,然后连 h 到 j,再销毁i 即可.虽然可以安全的删除 i 结点,但是是顺序查找找到 i,之后删除,时间复杂度是 O(n)级别的.具体做法就是:顺序查找整个单链表,找到要删除结点 i 的直接前驱 h,把 h额 next 指向i 的 nex

单链表-删除链表的节点出现问题

问题描述 删除链表的节点出现问题 我创建了一个链表,链表的第一个节点不是空白的.我想用free函数删除第一个节点,发现出错.删除其他的节点没有问题.不知道什么缘故. 解决方案 你的链表怎么定义的? 是 typeof struct Node { Node next; } Node * head这样定义的么? 那么你删除首节点要这么做 prehead = head; head = head->next; free(prehead); 解决方案二: 删除节点时: Node *s,*p; s=p->n

python实现:删除链表中等于给定值val的所有节点.求代码学习

问题描述 python实现:删除链表中等于给定值val的所有节点.求代码学习 例如:给出链表 1->2->3->3->4->5->3, 和 val = 3, 需要返回删除3之后的链表:1->2->4->5. 解决方案 python怎么考虑链表,是用类来实现链表节点吗? 如果不是,就简单了. def remove(arr): #arr=[1,2,3,3,4,5,3] arr_len = len(arr) for i in range(0,arr_len)

c++ 数据结构 链表 c-为什么删除链表后又倒着输出来了?

问题描述 为什么删除链表后又倒着输出来了? #include#include#includeusing namespace std;typedef struct node{ struct node* next; int number; int data;}NODE;void node_add(NODE**intint);void node_show(NODE*);void node_delete(NODE**);int main(){ NODE* head = NULL; node_add(&h

[华为机试练习题]24.删除链表中的重复节点、剩余节点逆序输出

题目 描述: 题目描述: 输入一个不带头节点的单向链表(链表的节点数小于100),删除链表中内容重复的节点(重复的节点全部删除),剩余的节点逆序倒排. 要求实现函数: void vChanProcess(strNode * pstrIn,strNode * pstrOut); [输入] pstrIn:输入一个不带头节点的单向链表 [输出] pstrOut:删除内容重复的节点(重复的节点全部删除),剩余节点逆序输出(不带头节点,链表第一个节点的内存已经申请). [注意]只需要完成该函数功能算法,中

删除链表的节点,然后再查询,编号会错误

问题描述 删除链表的节点,然后再查询,编号会错误 #include #include #include #include using namespace std; typedef int datatype; typedef struct person { datatype score; char name[20]; int number; struct person *llink, *rlink; }PE; void display(PE *head) { PE *p; cout << end

删除链表节点(java)

问题描述 删除链表节点(java) //deleteNode() O(1)= ((n-1)*O(1) + O(n)/2) static void deleteNode(Nodes head,Nodes x){ if(head == null || x == null) return ; //不是尾节点 if(x.next!=null){ Nodes temp = x.next; x.next = temp.next; x.data = temp.data; } //只有一个节点,头结点(尾节点)

删除重复结点的算法,哪里错了求解答,运行不了!!

问题描述 删除重复结点的算法,哪里错了求解答,运行不了!! void DeleteList(linklist &L){ linklist pqs; p=L->next ; while(p){ q=p->next; while(q) { if(q->data==p->data ) { s=q; q=s->next; free(s); } else q=q->next ; } p=p->next ;} } 解决方案 void RemoveDupNode(lin