Remove Duplicates from Sorted List II
阿新 • • 發佈:2021-12-05
Source
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Example Given 1->2->3->3->4->4->5, return 1->2->5. Given 1->1->1->2->3, return 2->3.
題解
上題為保留重複值節點的一個,這題刪除全部重複節點,看似區別不大,但是考慮到連結串列頭不確定(可能被刪除,也可能保留),因此若用傳統方式需要較多的if條件語句。這裡介紹一個處理連結串列頭節點不確定的方法——引入dummy node.
ListNode *dummy = new ListNode(0); dummy->next = head; ListNode *node = dummy;
引入新的指標變數dummy
,並將其next變數賦值為head,考慮到原來的連結串列頭節點可能被刪除,故應該從dummy處開始處理,這裡複用了head變數。考慮連結串列A->B->C
,刪除B時,需要處理和考慮的是A和C,將A的next指向C。如果從空間使用效率考慮,可以使用head代替以上的node,含義一樣,node比較好理解點。
與上題不同的是,由於此題引入了新的節點dummy
,不可再使用node->val == node->next->val
- 此題需要將值相等的節點全部刪掉,而刪除連結串列的操作與節點前後兩個節點都有關係,故需要涉及三個連結串列節點。且刪除單向連結串列節點時不能刪除當前節點,只能改變當前節點的
next
指向的節點。 - 在判斷val是否相等時需先確定
node->next
和node->next->next
均不為空,否則不可對其進行取值。
C++
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * };*/ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { if (head == NULL) return NULL; ListNode *dummy = new ListNode(0); dummy->next = head; ListNode *node = dummy; while (node->next != NULL && node->next->next != NULL) { if (node->next->val == node->next->next->val) { int val_prev = node->next->val; // remove ListNode node->next while (node->next != NULL && val_prev == node->next->val) { ListNode *temp = node->next; node->next = node->next->next; delete temp; } } else { node = node->next; } } return dummy->next; } };
Java
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null) return null; ListNode dummy = new ListNode(0); dummy.next = head; ListNode node = dummy; while(node.next != null && node.next.next != null) { if (node.next.val == node.next.next.val) { int val_prev = node.next.val; while (node.next != null && node.next.val == val_prev) { node.next = node.next.next; } } else { node = node.next; } } return dummy.next; } }
原始碼分析
- 首先考慮異常情況,head 為 NULL 時返回 NULL
- new一個dummy變數,
dummy->next
指向原連結串列頭。 - 使用新變數node並設定其為dummy頭節點,遍歷用。
- 當前節點和下一節點val相同時先儲存當前值,便於while迴圈終止條件判斷和刪除節點。注意這一段程式碼也比較精煉。
- 最後返回
dummy->next
,即題目所要求的頭節點。
複雜度分析
兩根指標(node.next 和 node.next.next)遍歷,時間複雜度為 O(2n). 使用了一個 dummy 和中間快取變數,空間複雜度近似為 O(1).