删除单链表节点O(1)

转载 2015年07月10日 16:27:39

一,题目

给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:

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

函数的声明如下:
void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);
二,分析

这是一道广为流传的Google面试题,能有效考察我们的编程基本功,还能考察我们的反应速度,更重要的是,还能考察我们对时间复杂度的理解。
在链表中删除一个结点,最常规的做法是从链表的头结点开始,顺序查找要删除的结点,找到之后再删除。由于需要顺序查找,时间复杂度自然就是O(n)了。我们之所以需要从头结点开始查找要删除的结点,是因为我们需要得到要删除的结点的前面一个结点。
“狸猫换太子法”:可以从给定要删除的结点得到它的下一个结点。这个时候我们实际删除的是它的下一个结点,在删除之前,我们需要需要把给定的结点的下一个结点的数据拷贝到给定的结点中,然后删除该节点的下一个节点。此时,时间复杂度为O(1)。
上面的思路还有一个问题:如果删除的结点位于链表的尾部,没有下一个结点,怎么办?我们仍然从链表的头结点开始,顺便遍历得到给定结点的前序结点,并完成删除操作。这个时候时间复杂度是O(n)。
那题目要求我们需要在O(1)时间完成删除操作,我们的算法是不是不符合要求?实际上,假设链表总共有n个结点,我们的算法在n-1总情况下时间复杂度是O(1),只有当给定的结点处于链表末尾的时候,时间复杂度为O(n)。那么平均时间复杂度[(n-1)*O(1)+O(n)]/n,仍然为O(1)。

#include <iostream>
using namespace std; 
struct Node
{
      int    data;
      Node*  next;

};
Node *creat()
{
    Node *head=new Node();
    head->data=0;
    head->next=NULL;
    for(int i=10;i>0;--i)
    {
        Node *temp=new Node();
        temp->data=i;
        temp->next=NULL;
        temp->next=head->next;
        head->next=temp; 
    } 
    return head;
} 
Node *findLastNode(Node *head,int data)
{
    while(head!=NULL&&head->data!=data)
    {
        head=head->next; 
    } 
    return head; 
} 
void deleteNode(Node *head,Node *del)
{
    if(del->next!=NULL)
    {
        Node *p = del->next ;
        del->data=del->next->data;
        del->next=del->next->next;
        delete p; 
    } 
    else
    {
       /*这是我们删除最后节点的办法*/ 
        Node *pre=findLastNode(head,9); 
        delete pre->next;
        pre->next=NULL; 
    } 
} 
void print(Node *head)
{
    while(head!=NULL)
    {
        cout<<head->data<<" ";
        head=head->next; 
    } 
} 
int main()
{

    Node *head=creat(); 
    print(head); 
    /*O(1)策略删除一个给定元素*/ 
    Node *del=findLastNode(head,8); 
    deleteNode(head,del); 

    /*O(n)策略删除结尾元素*/ 
    Node *del2=findLastNode(head,10); 
    deleteNode(head,del2); 

    cout<<endl; 
    print(head); 
}  

删除单向链表中的某一个节点

已知一个单向链表的表头head,写出一个删除某一个节点的算法,要求先找到此节点,然后删除。 #include using namespace std; typedef struct node ...

单向链表在O(1)时间内删除一个节点

单向链表在O(1)时间内删除一个节点

怎么删除一个没有头指针的单链表的一个节点?

怎么删除一个没有头指针的单链表的一个节点?

《算法之美》の链表问题の从链表中删除节点

问题:假设一个没有头指针的单链表。一个指针指向此单链表中间的一个节点(既不是第一个,也不是最后一个节点),请将该节点从单链表中删除。链表结点定义如下:struct ListNode{         ...
  • ACE1985
  • ACE1985
  • 2010年08月06日 14:48
  • 3485

删除单向链表中间的某个结点

class ListNode { public: int val; ListNode *next; bool removeNode(ListNode * pNode); ListNode (...

链表删除指定位置节点

给定一个链表要求删除指定位置的节点。 例如: 原链表:1->2->3->4->5 要求删除第2个位置节点 操作后链表:1->3->4->5 要求:不能创建新的节点 源码: class Node {...

单链表反转,要求空间复杂度O(1)

这是一道笔试题: 给你一个指向单链表表头的指针,要你把整个链表反转,并且空间复杂度为O(1)。链表节点结构和函数头已给出: struct LinkNode { int data; LinkN...

面试题13:在O(1)时间 内删除链表节点

题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。链表节点与函数的定义如下: struct ListNode { int value; ListNode*...

删除单链表中第i个节点

单链表的删除操作是将单链表的第i个节点删去。具体步骤如下: (1)找到节点ai-1的存储位置p,因为在单链表中节点ai的存储地址是在其直接前趋节点ai-1的指针域next中; (2)令p->nex...

单链表结点删除

习题11-8 单链表结点删除   (20分) 本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中所有存储了某给定值的结点删除。链表结点定义如下: struct ListNod...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:删除单链表节点O(1)
举报原因:
原因补充:

(最多只允许输入30个字)