剑指offer--用O(1)的时间复杂度删除链表的节点

来源:互联网 发布:郑州863软件孵化器 编辑:程序博客网 时间:2024/05/24 08:33

面试题13:给定单项链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。

//不带头结点的单链表struct ListNode{    int m_nKey;    ListNode *m_pNext;};//尾插void InsertTail(ListNode **head,int key){    ListNode *newnode = new ListNode();    newnode->m_nKey = key;    newnode->m_pNext = NULL;    if(*head == NULL)    {        *head = newnode;    }    else    {        ListNode *p = *head;        while(p->m_pNext != NULL)            p = p->m_pNext;        p->m_pNext = newnode;    }}/*假设该结点在链表中。如果不假设,我们需要O(n)的时间才能判断链表中是否包含该结点。基于O(1)的限制,只能把确保结点在链表中的要求推给函数调用者*/void DeleteNode(ListNode **head,ListNode *deletenode){    if(head==NULL || deletenode==NULL)        return;    //删除的节点不是尾节点    if(deletenode->m_pNext != NULL)    {        ListNode *p = deletenode->m_pNext;        deletenode->m_nKey = p->m_nKey;        deletenode->m_pNext = p->m_pNext;        delete(p);        p = NULL;    }    //链表只有一个节点,删除的是尾节点    else if(*head == deletenode)    {        delete deletenode;        deletenode = NULL;        *head = NULL;    }    //链表有多个节点,删除的是尾节点    else    {        ListNode *p = *head;        while(p->m_pNext != deletenode)        {             p = p->m_pNext;        }        p->m_pNext = NULL;        delete deletenode;        deletenode = NULL;    }}void Show(ListNode *head){    for(ListNode *p=head;p!=NULL;p=p->m_pNext)    {        cout<<p->m_nKey<<ends;    }    cout<<endl;}int main(){    ListNode *head = NULL;    for(int i=0;i<10;i++)    {        InsertTail(&head,i);    }    cout<<"删除前:";    Show(head);    cout<<"删除第三个元素:";    DeleteNode(&head,head->m_pNext->m_pNext);    Show(head);    cout<<"删除首元素:";    DeleteNode(&head,head);    Show(head);    ListNode *p = head;    while(p->m_pNext != NULL) p = p->m_pNext;    cout<<"删除尾元素:";    DeleteNode(&head,p);    Show(head);}

这里写图片描述

对于一个n-1非尾结点而言,可以在O(1)时把下一个结点的内存复制覆盖要删除的结点,并删除下一个结点;对于尾结点来说,由于仍需要顺序查找,时间复杂度为O(n)。总的时间复杂度是[(n-1)*O(1)+O(n)]/n,结果是O(1)。

原创粉丝点击