zoukankan      html  css  js  c++  java
  • 剑指offer--面试题13

    题目:以O(1)的时间复杂度删除单链表中的某个节点

    自己所写代码如下:

    //以O(1)时间删除链表节点
    //要求:单向链表,头指针,待删节点指针
    
    //链表节点
    struct ListNode
    {
        int m_nValue;
        ListNode* m_pNext;
    };
    //O(n)的解法:从头遍历,找到pToBeDeleted所指节点的前一个节点再进行删除
    void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
    {
        if(pListHead == NULL || *pListHead == NULL || pToBeDeleted == NULL)
            return;
        
        ListNode* pNode = *pListHead;
        if(pNode == pToBeDeleted)   //对pToBeDeleted指向头结点情况的处理
        {
            *pListHead = (*pListHead)->m_pNext;
            delete pToBeDeleted;
            pToBeDeleted = NULL;
        }
        else
        {
            while(pNode->m_pNext != NULL && pNode->m_pNext != pToBeDeleted)
                pNode = pNode->m_pNext ;
    
            if(pNode->m_pNext == NULL)
            {
                cout<<"pToBeDeleted不在链表中!"<<endl;
                return;
            }
    
            pNode->m_pNext = pToBeDeleted->m_pNext;
            delete pToBeDeleted;
            pToBeDeleted = NULL;
    
        }
        
    }
    
    //O(1)的解法:复制后一个节点以覆盖待删节点,再删除重复的后一个节点
    void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
    {
        if(pListHead == NULL || *pListHead == NULL || pToBeDeleted == NULL)
            return;
        
        ListNode* pNode = *pListHead;
        if(pNode == pToBeDeleted)
        {
            *pListHead = (*pListHead)->m_pNext;
            delete pToBeDeleted;
            pToBeDeleted = NULL;
        }
        else
        {
            pNode = pToBeDeleted->m_pNext;
            //排除pToBeDeleted指向尾节点的情形
            if(pNode == NULL)
            {
                pNode = *pListHead;
                while(pNode->m_pNext != pToBeDeleted)
                    pNode = pNode->m_pNext ;
                
                pNode->m_pNext = NULL;
                
                delete pToBeDeleted;
                pToBeDeleted = NULL;
            }
            else
            {
                pToBeDeleted->m_nValue = pNode->m_nValue;
                pToBeDeleted->m_pNext = pNode->m_pNext;
                delete pNode;
                pNode = NULL;
            }
            
        }
    }

    在以上O(1)的代码中,自己的想法有些呆板,具体来说:采用复制覆盖的方法则应考虑的是pToBeDeleted指向尾节点的特殊情况(此时,无法复制!)

    而非pToBeDeleted指向头结点的情况(这是O(n)的特殊情况!)!!!

    O(n)的方法:需要找前驱节点,所以考虑头结点的特殊情况;

    O(1)的方法:需要找后继节点,所以考虑尾节点的特殊情况。

    代码修改如下:

    //O(1)的解法:复制后一个节点以覆盖待删节点,再删除重复的后一个节点
    void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
    {
        if(pListHead == NULL || *pListHead == NULL || pToBeDeleted == NULL)
            return;
        
        ListNode* pNode = pToBeDeleted->m_pNext;
        //排除pToBeDeleted指向尾节点的情形
        if(pNode == NULL)
        {
            pNode = *pListHead;
            if(pNode == pToBeDeleted)
            {
                delete pToBeDeleted;
                *pListHead = pToBeDeleted = NULL;
            }
            else
            {
                while(pNode->m_pNext != pToBeDeleted)
                    pNode = pNode->m_pNext;
            
                pNode->m_pNext = NULL;
                
                delete pToBeDeleted;
                pToBeDeleted = NULL;
            }
            
        }
        else
        {
            pToBeDeleted->m_nValue = pNode->m_nValue;
            pToBeDeleted->m_pNext = pNode->m_pNext;
            delete pNode;
            pNode = NULL;
        }
            
    }

    和参考代码相一致!赞一个!

    总结:1、突破常规思维,删除节点不一定需要从头遍历链表,可以用下一结点复制并覆盖待删节点,最后再删除重复的下一结点。

       2、考虑问题全面性:若待删节点为尾节点,则下一个节点为空;若整个链表仅一个节点,删除后,头结点同时设为NULL。

          这些都需要特殊对待!!!

    清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
  • 相关阅读:
    Java中接口对象实现回调
    推荐算法之计算相似度
    mahout入门实例2-Mahout单机开发环境介绍(参考粉丝日志)
    mahout入门实例-基于 Apache Mahout 构建社会化推荐引擎-实战(参考IBM)
    windows下gvim使用及常见命令
    一道C语言的问题(转)
    android开发手记一
    数据结构之有关图的算法(图的邻接表示法)
    Week of Code:GG
    HDU 5587:Array
  • 原文地址:https://www.cnblogs.com/hello-yz/p/3251464.html
Copyright © 2011-2022 走看看