删除链表的某一个节点
题目:给定单链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表的定义如下:
struct ListNode
{
int val;
ListNode next;
}
void DeleteNode(ListNode * Head,ListNode * ptr);
看完这个题目,大家就感觉很开心,觉得这个题目非常的简单。我们只需要找到这个结点的前一个结点,然后删除这个结点。
如下:
这时候我们就感觉自己已经完成了任务,但是我们可以来看看这个程序,我们需要找到要删除结点的前一个结点,则需要遍历一遍这个链表,我们需要的时间复杂度即为O(n)
我们怎样才可以将我们的时间复杂度变为O(1)呢,我们可以做如下的假设:
- 若删除的为头结点;
- 若删除的为尾结点;
- 若删除的是中间结点。
接下来,我们就一种一种的分析:
TO1:
如果是头结点,我们直接删除头结点,这个比较简单,时间复杂度为O(1);
TO2:
如果是尾结点,这时候我们就需要遍历整个链表去找到尾结点的前一个结点,然后去删除尾结点,时间复杂度即为O(n);
TO3:
我们直接将这个结点的下一个结点的 val 和naxt 赋值到要这个结点,然后删除下一个接结点,时间复杂度为O(1)
代码如下:
void DeleteNode(ListNode * Head,ListNode * ptr);
{
if(Head&&ptr)
return ;
if(ptr->next!=NULL)
{
ListNode *q=ptr->next;
ptr->val=q->val;
ptr->next=q->next;
delete q;
q=NULL;
}
else if(Head==ptr)
{
delete Head;
Head=NULL;
ptr=NULL;
}
else
{
ListNode *q=Head;
while(q->next!=ptr)
{
q=q->next;
}
q->next=ptr->next;
delete ptr;
ptr=NULL;
}
}
虽然删除尾结点的时候,他的时间复杂度是O(n)。但是平均复杂度是((n-1)*O(1)+O(n))/O(n)=O(1);