zoukankan      html  css  js  c++  java
  • (剑指Offer)面试题13:在O(1)时间内删除链表结点

    题目:

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

    struct ListNode{
    int val;
    ListNode* next;
    };
    
    void deleteNode(ListNode** pListHead,ListNode* pToBeDeleted)
    

    思路:

    删除链表结点的一般思路是:从头指针开始遍历,找到要删除结点的前一结点pPrev,然后pPrev->next=pToBeDeleted->next,(还需考虑删除结点是否为头结点),这样的时间复杂度为O(n)。

    而题目要求为O(1),找到删除结点的前一结点复杂度为O(n),但找到后一结点的复杂度为O(1),如果我们把后一结点的东西拷贝到要删除结点上,再把后一结点删除,岂不就是相当于把当前需要删除的结点删除了?

    ListNode* pNext=pToBeDeleted->next;
    pToBeDeleted->val=pNext->val;
    pToBeDeleted->next=pNext->next;
    delete pNext;
    pNext=NULL;

    考虑特殊情况,如果要删除的结点为头结点和尾结点怎么办?

    头结点:要删除的结点为头结点,删除之后,链表为空,此时需要将头结点置为NULL,这时候改变的头指针的内存地址,因此需要传递二级指针,*pHead=NULL;

    尾结点:要删除的结点为尾结点,尾结点没有后一结点,因此,不能通过上述方法来解决,还要回到传统的遍历方法,找到它的前一结点,然后将它的下一结点置为NULL,同时删除尾指针。

    代码:

    struct ListNode{
    int val;
    ListNode* next;
    };
    
    void deleteNode(ListNode** pListHead,ListNode* pToBeDeleted){
        if(pListHead==NULL || pToBeDeleted==NULL)
            return;
        if(pToBeDeleted->next!=NULL){
            ListNode* pNext=pToBeDeleted->next;
            pToBeDeleted->val=pNext->val;
            pToBeDeleted->next=pNext->next;
            delete pNext;
            pNext=NULL;
        }
        else if(*pListHead==pToBeDeleted){
            delete pToBeDeleted;
            pToBeDeleted=NULL;
            *pListHead=NULL;
        }
        else{
            ListNode* pNode=*pListHead;
            while(pNode->next!=pToBeDeleted)
                pNode=pNode->next;
            pNode->next=NULL;
            delete pToBeDeleted;
            pToBeDeleted=NULL;
        }
    }
  • 相关阅读:
    你的项目中使用过哪些JSTL标签?
    web资源的运行原理
    Java与Andriod的区别和关系
    request.getAttribute()和 request.getParameter()有何区别?
    groupId和artifactId
    MySQL锁(一)全局锁:如何做全库的逻辑备份?
    SPRINGBOOT集成SWAGGER2
    RabbitMQ 消息中间件(三)
    RabbitMQ 消息中间件(二)
    RabbitMQ 消息中间件(一)
  • 原文地址:https://www.cnblogs.com/AndyJee/p/4643070.html
Copyright © 2011-2022 走看看