刪除鍊錶結點(時間複雜度為O 1 ))

2021-06-20 19:42:02 字數 1579 閱讀 5081

題目:給定鍊錶的頭指標和乙個結點指標,在o(1)時間刪除該結點。鍊錶結點的定義如下:

struct listnode

;函式的宣告如下:

void deletenode(listnode* plisthead, listnode* ptobedeleted);

分析:這是一道廣為流傳的google面試題,能有效考察我們的程式設計基本功,還能考察我們的反應速度,更重要的是,還能考察我們對時間複雜度的理解。

在鍊錶中刪除乙個結點,最常規的做法是從鍊錶的頭結點開始,順序查詢要刪除的結點,找到之後再刪除。由於需要順序查詢,時間複雜度自然就是o(n) 了。

我們之所以需要從頭結點開始查詢要刪除的結點,是因為我們需要得到要刪除的結點的前面乙個結點。我們試著換一種思路。我們可以從給定的結點得到它的下乙個結點。這個時候我們實際刪除的是它的下乙個結點,由於我們已經得到實際刪除的結點的前面乙個結點,因此完全是可以實現的。當然,在刪除之前,我們需要需要把給定的結點的下乙個結點的資料拷貝到給定的結點中。此時,時間複雜度為o(1)。

上面的思路還有乙個問題:如果刪除的結點位於鍊錶的尾部,沒有下乙個結點,怎麼辦?我們仍然從鍊錶的頭結點開始,順序遍歷得到給定結點的前序結點,並完成刪除操作。這個時候時間複雜度是o(n)。

那題目要求我們需要在o(1)時間完成刪除操作,我們的演算法是不是不符合要求?實際上,假設鍊錶總共有n個結點,我們的演算法在n-1總情況下時間複雜度是o(1),只有當給定的結點處於鍊錶末尾的時候,時間複雜度為o(n)。那麼平均時間複雜度[(n-1)*o(1)+o(n)]/n,仍然為o(1)。

基於前面的分析,我們不難寫出下面的**。

參考**:

[cpp]view plain

copy

///// delete a node in a list

// input: plisthead - the head of list

//        ptobedeleted - the node to be deleted

///void

deletenode(listnode* plisthead, listnode* ptobedeleted)  

// if ptobedeleted is the last node in the list

else

// deleted ptobedeleted

pnode->m_pnext = null;  

delete

ptobedeleted;  

ptobedeleted = null;  

}  }   

值得注意的是,為了讓**看起來簡潔一些,上面的**基於兩個假設:(1)給定的結點的確在鍊錶中;(2)給定的要刪除的結點不是鍊錶的頭結點。不考慮第乙個假設對**的魯棒性是有影響的。至於第二個假設,當整個列表只有乙個結點時,**會有問題。但這個假設不算很過分,因為在有些鍊錶的實現中,會建立乙個虛擬的煉表頭,並不是乙個實際的鍊錶結點。這樣要刪除的結點就不可能是鍊錶的頭結點了。當然,在面試中,我們可以把這些假設和面試官交流。這樣,面試官還是會覺得我們考慮問題很周到的。

ps:假設要刪除a節點,a.next==b。則刪除b,並將b的值賦給a,這樣就等於刪除了a節點。

演算法題14 刪除鍊錶結點(時間複雜度為O 1 ))

題目 給定鍊錶的頭指標和乙個結點指標,在o 1 時間刪除該結點。鍊錶結點的定義如下 struct listnode 函式的宣告如下 void deletenode listnode plisthead,listnode ptobedeleted 分析 這是一道廣為流傳的google面試題,能有效考察...

刪除鍊錶結點要求O 1 時間複雜度

一,題目 給定鍊錶的頭指標和乙個結點指標,在 o 1 時間刪除該結點。鍊錶結點的定義如下 struct listnode 函式的宣告如下 void deletenode listnode plisthead,listnode ptobedeleted 二,分析 這是一道廣為流傳的 google 面試...

O 1 時間複雜度刪除鍊錶元素

package lineartable 鍊錶節點類 class node 鍊錶類 public class linktable 增加節點 public void addnode node node end.next node 刪除節點 時間複雜度為o 1 無需遍歷鍊錶元素 public void d...