1. 程式人生 > >劍指Offer之在O(1)時間刪除鏈表節點

劍指Offer之在O(1)時間刪除鏈表節點

print 那是 idt bsp 技術 rgs != str 順序

題目描述

  給定單向鏈表的頭指針和一個節點指針,定義一個函數在O(1)時間刪除該節點。

解題思路

  在單向鏈表中刪除一個節點,最常規的做法無疑是從鏈表的頭結點開始,順序的遍歷查找要刪除的節點,並在鏈表中刪除該節點。這種思路由於需要順序查找,時間復雜度自然就是$O(n)$了。

技術分享

  之所以需要從頭開始查找,是因為我們需要得到將刪除的節點的前面一個節點。在單向鏈表中,節點中沒有指向前一個節點的指針,所以只好從鏈表的頭結點開始順序查找。那是不是一定需要得到被刪除的節點的前一個節點呢?答案是否定的。我們可以很方便地得到要刪除的節點的下一個節點。如果我們把下一個節點的內容復制到需要刪除的節點上覆蓋原有的內容,再把下一個節點刪除,這樣就相當於把當前需要刪除的節點刪除了。具體操作如下圖所示:

技術分享

  上述思路需要註意兩個問題:1、如果要刪除的節點位於鏈表的尾部,那麽它就沒有下一個節點,我們仍然需要從鏈表的頭結點開始,順序的遍歷得到該節點的前序節點,並完成刪除操作。2、如果鏈表只有一個節點,而我們又要刪除鏈表的頭結點(也是尾節點),此時我們在刪除節點後,還需要把鏈表的頭結點設置為NULL。

Java代碼如下:

package com.swordOffer.deleteNodeInList10;

/**
 * Created by Feng on 2017/5/7.
 * 給定單向鏈表的頭指針和一個節點指針,定義一個函數在O(1)時間刪除該節點。
 */
public
class DeleteNodeInList { public static void main(String[] args) { ListNode node1 = new ListNode(1); ListNode node2 = new ListNode(2); ListNode node3 = new ListNode(3); node1.next = node2; node2.next = node3; deleteNodeInList(node1, node2);
while (node1 != null) { System.out.print(node1.val + " "); node1 = node1.next; } } public static void deleteNodeInList(ListNode pHead, ListNode deleteNode) { //判斷節點是否為空 if (pHead == null || deleteNode == null) { return; } //鏈表有多個節點,要刪除的不是尾節點:O(1)時間 if (deleteNode.next != null) { ListNode pNext = deleteNode.next; deleteNode.val = pNext.val; deleteNode.next = pNext.next; } else if (pHead == deleteNode) { //鏈表只有一個結點,刪除頭結點(也是尾結點):O(1)時間 deleteNode = null; pHead = null; } else { //鏈表有多個節點,要刪除的是尾節點:O(n)時間 ListNode pNode = pHead; while (pNode.next != deleteNode) { pNode = pNode.next; } pNode.next = null; deleteNode = null; } } } class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } }

劍指Offer之在O(1)時間刪除鏈表節點