1. 程式人生 > >用O(1)的時間複雜度刪除單鏈表中的某個節點

用O(1)的時間複雜度刪除單鏈表中的某個節點

給定連結串列的頭指標和一個結點指標,在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; } }