劍指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 上進行下載。