lintCode(372)——在O(1)时间复杂度删除链表节点

题目描述:

给定一个单链表中的表头和一个等待被删除的节点。请在在O(1)时间复杂度删除该链表节点。并在删除该节点后,返回表头。

样例:给定 1->2->3->4,和节点 3,返回 1->2->4。


这是一道广为流传的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)。

基于前面的分析,我们不难写出下面的代码。

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param node: a node in the list should be deleted
     * @return: nothing
     */
    void deleteNode(ListNode** pHead,ListNode *node) {
        // write your code here
        if(pHead==NULL||node==NULL)
            return;
        //要删除的结点不是尾结点
        if(node->next!=NULL){
        ListNode* pNext=node->next;
        node->val=pNext->val;
        node->next=pNext->next;
        
        delete pNext;
        pNext=NULL;
        }
        //链表只有一个结点,删除头结点(也是尾结点)
        else if(*pHead==node)
        {
            delete node;
            node=NULL;
            *pHead=NULL;
        }
        //要删除的结点是尾结点,且链表有多个结点
        else
        {
            ListNode* pNode=*pHead;
            while(pNode->next!=node)
            {
                pNode=pNode->next;
            }
            pNode->next=NULL;
            delete node;
            node=NULL;
        }
    }
    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值