剑指offer 面试题13—在O(1)时间删除链表节点

题目:

给你一个单链表的表头,再给你其中某个结点的指针,要你删除这个结点,条件是你的程序必须在O(1)的时间内完成删除。


基本思想:

普通的删除方法,首先通过表头,找到待删除结点(设为B)的前一个结点(设为A),将A的指向改一下就行,然后删除掉B结点就行了。要删除的结点一定要delete掉。

void DeleteNode_On(ListNode *pHead, ListNode *pDelete)
{
    printf("delete:%d\n", pDelete->val);
    ListNode *s = pHead;
    while(s->next != pDelete)
        s = s->next;
    s->next = s->next->next;
    delete(pDelete);
}

这个算法主要耗时在于查找前一个结点,所以是O(n)的算法。

那么既然要求是O(1),显然不能再去for一遍了,联想到数组的删除,这个问题就比较好解决了。

首先我们很容易就能得到待删除结点,即B结点的后一个结点C,然后将C的值赋值给B结点的值,相当于数组删除时候的覆盖,现在B结点和C结点一模一样了,接下来就相当简单了吧,我们不删B,直接利用B删掉C就行了,方法简单,时间O(1)。


如果要删除的节点位于链表的尾部,那么它就没有下一个节点。我们仍然需要从链表的头节点开始,顺序遍历。

如果链表中只有一个节点,此时我们在删除节点之后,还需要把链表的头结点设置为NULL。

void DeleteNode_O1(ListNode *pHead, ListNode *pDelete)
{
    printf("delete:%d\n", pDelete->val);
    if(pDelete->next != NULL) //如果pDelete不是尾结点, 则让后一个结点覆盖掉pDelete, 然后删除后一个结点
    {
		ListNode *pNext = pDelete->next;
        pDelete->val = pNext->val;
        pDelete->next = pNext->next;
        delete(pNext);
		pNext=NULL;
    }
	else if(*pHead == pDelete)//链表只有一个节点,删除头结点(也是尾节点)
	{
		delete(pDelete);
		pDelete=NULL;
		*pHead=NULL;
	}
    else// 如果链表中有多个节点,删除尾节点的情况,顺序遍历找到前节点
    {
        ListNode *s = *pHead;
        while(s->next != pDelete)
            s = s->next;

        s->next=NULL;
		delete(pDelete);
		pDelete=NULL;
    }
}

对于n-1个非尾节点,O(1)。

对于尾节点,O(n)。


平均时间复杂度:

[(n-1)*O(1)+O(n)]/n=O(1)。


引用:

http://www.2cto.com/kf/201408/322311.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值