1. 程式人生 > >劍指offer之刪除連結串列節點

劍指offer之刪除連結串列節點


title: 刪除連結串列節點
date: 2018-08-06 08:28:59
tags: 劍指offer

1. 題目

在 O(1) 時間內刪除連結串列節點。

給定單向連結串列節點的頭指標和一個節點指標(使用 java 實現,因此我的程式碼中頭結點作為一個變數定義在類中),定義一個函式在 O(1) 時間內刪除該節點。

2. 思路

在單向連結串列中刪除節點按照常規的思路來說就是從頭開始遍歷,查詢到需要刪除的節點,並在連結串列中刪除該節點。但是這種做法的時間複雜度為 O(N),並不符合題目要求,因此需要考慮一下其他的思路。

首先,看一下連結串列內部使用的資料結構:

private class Node{
    private Object value;
    private Node next;

    public Node(Object value,Node next){
        this.value = value;
        this.next = next;
    }
}

一個節點包含這個節點的值以及下一個節點的引用。如果要刪除這個節點的值,可以通過將下一個節點的內容複製到要刪除的這個節點,通過這樣的動作也是可以刪除節點的。例如,有這樣的一個連結串列:

1 -> 2 -> 3 -> 4 -> 5

如果要刪除 3 這個節點,那麼,我們可以將 4 這個節點的值覆蓋 3 這個節點的值,用 4 這個節點的 next 變數覆蓋 3 這個節點的 next 變數,這個過程下來,連結串列中就將 3 這個節點刪除了。

但是這個過程需要注意,如果這個節點是最後一個節點,就沒辦法通過上述的方法來完成,只能通過常規的方法來解決了。

還有一個情況需要注意,如果這個節點是頭結點並且整個連結串列中只有一個節點,這時候我們就需要將連結串列的頭結點置為空。程式碼的實現如下:

private Node head;
private Node tail;

public void deleteNode
(Node toBeDelete){ if(head==null || toBeDelete==null) return; if(toBeDelete.next!=null){ Node nextNode = toBeDelete.next; toBeDelete.value = nextNode.value; toBeDelete.next = nextNode.next; }else if(head.value.equals(toBeDelete.value)){ head = null; tail = null; }else{ Node currentNode = head; while(!toBeDelete.value.equals(currentNode.next.value)){ currentNode = currentNode.next; } currentNode.next = null; } } // 列印連結串列的方法 public void printLinkList(){ Node currentNode = head; while(currentNode!=null){ System.out.println(currentNode.value); currentNode = currentNode.next; } } // 連結串列新增元素的方法 public void add(Object value){ Node temp = new Node(value,null); if(head==null){ head = temp; tail = temp; }else{ tail.next = temp; tail = tail.next; } }

3. 注意點

這個方法的時間複雜度是不是 O(1) 呢?答案是肯定的,其時間複雜度為 [ (n-1)*O(1) + O(n) ] / n = O(1)。

這個思路是基於一個假設上實現的,就是要刪除的元素需要在連結串列內,為了符合時間複雜度為 O(1) 的要求,就沒辦法在函式中進行判斷,因此需要由呼叫該函式的人來保證。這在面試過程中可以和麵試官進行探討,可以讓面試官對我們有一個更好的印象。

詳細的程式碼可以上 github 上進行下載。