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