用O(1)的時間複雜度刪除單鏈表中的某個節點
阿新 • • 發佈:2019-02-08
給定連結串列的頭指標和一個結點指標,在O(1)時間刪除該結點。連結串列結點的定義如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
函式的宣告如下:
void DeleteNode(ListNode pListHead, ListNode pToBeDeleted)
一般單鏈表刪除某個節點,需要知道刪除節點的前一個節點,則需要O(n)的遍歷時間,顯然常規思路是不行的。在仔細看題目,換一種思路,既然不能在O(1)得到刪除節點的前一個元素,但我們可以輕鬆得到後一個元素,這樣,我們何不把後一個元素賦值給待刪除節點,這樣也就相當於是刪除了當前元素。可見,該方法可行,但如果待刪除節點為最後一個節點,則不能按照以上思路,沒有辦法,只能按照常規方法遍歷,時間複雜度為O(n),是不是不符合題目要求呢?可能很多人在這就會懷疑自己的思考,從而放棄這種思路,最後可能放棄這道題,這就是這道面試題有意思的地方,雖看簡單,但是考察了大家的分析判斷能力,是否擁有強大的心理,充分自信。其實我們分析一下,仍然是滿足題目要求的,如果刪除節點為前面的n-1個節點,則時間複雜度為O(1),只有刪除節點為最後一個時,時間複雜度才為O(n),所以平均的時間複雜度為:(O(1) * (n-1) + O(n))/n = O(1);仍然為O(1).下面見程式碼:
/* Delete a node in a list with O(1)
* input: pListHead - the head of list
* pToBeDeleted - the node to be deleted
*/
void DeleteNode(ListNode pListHead, ListNode pToBeDeleted)
{
if (pListHead == null || pToBeDeleted == null)
return;
if (pToBeDeleted.next != null ) {
ListNode pNext = pToBeDeleted.next;
pToBeDeleted.next = pNext.next;
pToBeDeleted.val= pNext.val;
}
else { //待刪除節點為尾節點
ListNode pTemp = pListHead;
while(pTemp.next != pToBeDeleted)
pTemp = pTemp.next;
pTemp.next = null;
}
}