剑指offer-13:在O(1)时间删除链表结点

来源:互联网 发布:函数式编程的优点 编辑:程序博客网 时间:2024/06/11 21:16

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

4月份找实习时滴滴视频面,就是出的这道题目,当时舍友提示说覆盖即可。

分析:

  • 一般的单链表中删除节点,遍历该链表,发现下一个是待删点,则删除。从头查找复杂度是O(n),因为我们需要找到待删点的前一个点。
  • 题目给定该结点的指针,要删除该结点,直接删则链表就断了。
  • 链表利用指针连接起来,非常灵活。可以把待删节点的下一个节点复制给待删点,然后删掉后面的点。就可以达到题目要求的结果。

注意:

  • 此题思路清晰,需要关注几个边界情况。如待删点为尾结点时,则必须从头开始遍历得到次尾结点。
  • 如果链表中只有一个结点,删除该结点,则需要把头指针置空。
  • 其余则属于正常情况的删除即可。

代码:

// offer-13-O(1)ListDelete.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>using namespace std;// 链表结点定义struct ListNode{    int value;    ListNode * pnext;};// 删除某给定的结点void DeleteNode(ListNode ** pListHead, ListNode * pToBedelete){    // 指针判断    if(!pListHead || !pToBedelete)        return;    // 如果不是尾结点,属于正常中间的某结点    if(pToBedelete->pnext != nullptr)    {        ListNode * ptmp = pToBedelete->pnext;        pToBedelete->value = ptmp->value;        pToBedelete->pnext = ptmp->pnext;        delete ptmp;        ptmp = nullptr;    }    // 如果是尾结点,判断是不是只有一个结点    else if(*pListHead == pToBedelete)    {        delete pToBedelete;        pToBedelete = nullptr;        *pListHead = nullptr;    }    // 如果是尾结点且链表有多个结点,需从头遍历    else    {        ListNode * ptmp = *pListHead;        while(ptmp->pnext != pToBedelete)        {            ptmp = ptmp->pnext;        }        ptmp->pnext = nullptr;        delete pToBedelete;        pToBedelete = nullptr;    }}int _tmain(int argc, _TCHAR* argv[]){    return 0;}

对于n-1个非尾结点而言,可以在O(1)时间把下一个结点的内存复制到需要删除的结点,并删除下一个结点;

对于尾结点而言,仍然需要顺序查找,时间复杂度是O(n)。总的平均时间复杂度是[(n1)O(1)+O(n)]/n=O(1),符合要求。

但是它还基于一个假设:要删除的结点的确在链表中。我们需要O(n)的时间才可以判断链表中是否包含某个结点,因此确保工作交给了函数的调用者。

阅读全文
0 0
原创粉丝点击