题目:给定单向链表的头指针和一个结点指针,定义一个函数在o(1)时间删除该结点。
解析:我们要删除结点i,先把i的下一个结点j的内容复制到i,然后把i的指针指向结点j的下一个结点。此时再删除结点j,效果刚好是把结点i给删除了。如果要删除的结点位于链表的尾部,那么他就没有下一个结点,我们仍然需要从链表的头结点开始,顺序遍历得到该结点的前序结点,并完成删除操作。如果删除的结点位于头结点,我们也需要特殊处理。以下代码是我自己写的。#include<iostream>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
};
void show(ListNode *pHead);
void appendTail(ListNode **pHead,int val)
{
ListNode *pNew = new ListNode;
pNew->next = NULL;
pNew->val = val;
if(*pHead == NULL)
{
*pHead = pNew;
}
else
{
ListNode *tmp = *pHead;
while(tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = pNew;
}
}
void deleteNode(ListNode **pHead,ListNode *pCur)
{
if(*pHead == NULL || pCur == NULL)
{
return;
}
//当删除元素在链表头部
if(*pHead == pCur)
{
(*pHead)= pCur->next;
delete pCur;
return;
}
//当删除元素在末尾
if(pCur->next == NULL)
{
ListNode *tmp = *pHead;
while(tmp->next != pCur)
{
tmp = tmp->next;
}
tmp->next = NULL;
delete pCur;
return;
}
pCur->val = pCur->next->val;
ListNode *p = pCur->next;
pCur->next = p->next;
delete p;
return;
}
void show(ListNode *pHead)
{
while(pHead)
{
cout<<pHead->val<<endl;
pHead = pHead->next;
}
}
int main(void)
{
ListNode *pHead = NULL;
for(int i = 0; i < 1; ++i)
{
appendTail(&pHead,i);
}
ListNode *pCur = pHead;
for(int i = 0; i < 10; ++i)
{
pCur = pCur->next;
}
deleteNode(&pHead,pCur);
show(pHead);
system("pause");
return 0;
}
剑指offer上的代码:void deleteNode(ListNode **pListHead,ListNode *pVal)
{
if(!pListHead || !pVal)
return;
if(pVal->next != NULL)
{
ListNode *pNext = pVal->next;
pVal->val = pNext->val;
pVal->next = pNext->next;
delete pNext;
pNext = NULL;
}
else if(*pListHead == pVal)
{
delete pVal;
pVal = NULL;
*pListHead = NULL;
}
else
{
ListNode *pNode = *pListHead;
while(pNode->next != pVal)
{
pNode = pNode->next;
}
pNode->next = NULL;
delete pVal;
pVal = NULL;
}
}
时间复杂度分析:对于n-1个非尾节点而言,我们可以在o(1)时间内把下一个结点的内容复制到要删除的结点中,并删除下一个结点。对于尾结点而言,由于仍然需要顺序查找,时间复杂度为o(n)。因此总得时间复杂度还是o(1)。