刪除鏈表的某一個節點
題目:給定單鏈表的頭指針和一個節點指針,定義一個函數在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);