1. 程式人生 > >"Coding Interview Guide" -- 刪除無序單鏈表中值重復出現的節點

"Coding Interview Guide" -- 刪除無序單鏈表中值重復出現的節點

其中 style 位置 next con 無序集合 ash div pub

題目

  給定一個無序單鏈表的頭節點head,刪除其中值重復出現的節點

  例如,1->2->3->3->4->4->2->1->1->null,刪除值重復的節點之後為1->2->3->4->null

 

要求

  實現兩種方法:

  1. 如果鏈表長度為N,時間復雜度達到O(N)

  2. 空間復雜度為O(1)

分析

  鏈表是一種邏輯有序,儲存位置無序且可非連續的數據結構,鏈表是線性表的一種,它有0個或多個節點組成,除了第一個節點外每個節點都一個直接前驅節點,除了最後一個節點外,每一個節點都有一個直接後繼節點。節點中不僅存儲著該節點自身的數據信息還存儲該節點的前驅後繼節點的存儲位置信息。

  對於方法1,HashSet是一種無序集合,該集合不允許有重復元素。可以通過使用HashSet來判斷元素是否重復,如果當前訪問的鏈表節點不在HashSet中,則將該節點放進集合中,如果當前訪問的鏈表節點與當前HashSet中的某個元素相同,則刪除鏈表中的該節點。整個過程只需遍歷一次鏈表,所以時間復雜度為O(N),因為借助了HashSet,所以空間復雜度為O(N)

 1 public void removeRepeat1(Node head)
 2 {
 3     if(head == null) { return; }
 4 
 5     HashSet<Integer> set = new
HashSet<>(); 6 Node pre = head; 7 Node cur = head.next; 8 9 set.add(head.value); 10 while(cur != null) 11 { 12 if(set.contains(cur.value)) 13 { 14 pre.next = cur.next; // 刪除重復節點 15 } 16 else 17 { 18 set.add(cur.value);
19 pre = cur; 20 } 21 cur = cur.next; 22 } 23 }

  方法2要求額外空間復雜度為O(1),表示不能使用額外的數據結構,所以可以對鏈表中的每一個元素,都訪問一次鏈表,如果有重復值則刪除,因為對於每一個元素都要遍歷一個鏈表查看有沒有重復值,所以時間復雜度為O(N^2)

 1 public void removeRepeat2(Node head)
 2 {
 3     if(head == null) { return; }
 4 
 5     Node pre = null;
 6     Node cur = head;
 7     Node next = null;
 8 
 9     while(cur != null)
10     {
11     pre = cur;
12     next = cur.next;
13     while(next != null)           // 對每一個元素都遍歷一次鏈表
14     {
15             if(next.value == cur.value)
16         {
17             pre.next = next.next;   // 刪除重復值
18         }
19         else
20         {
21         pre = next;
22         }
23         next = next.next;
24     }
25     cur = cur.next;
26     }
27 }

來源:左程雲老師《程序員代碼面試指南》

"Coding Interview Guide" -- 刪除無序單鏈表中值重復出現的節點