力扣LeetCode #82 刪除排序連結串列II(DeleteDuplicates)
阿新 • • 發佈:2021-01-26
- 題目描述
給定一個排序連結串列,刪除所有含有重複數字的節點,只保留原始連結串列中沒有重複出現的數字。
來源:LeetCode
- 示例
- 示例 1:
輸入: 1->2->3->3->4->4->5
輸出: 1->2->5 - 示例 2:
輸入: 1->1->1->2->3
輸出: 2->3
- 思路分析
- 本題和#83有點相像,但本題僅儲存沒有重複出現的元素。相比於#83,頭節點和尾節點需要特殊考慮,以及新連結串列的頭節點確定相對比較麻煩。
- 因為連結串列是有序的,那麼很容易判斷一個元素是否重複。我們定義
t
e
m
p
temp
①如果滿足 t e m p . v a l < h e a d . v a l < h e a d . n e x t . v a l temp.val<head.val<head.next.val
②如果不滿足,說明 h e a d head head一定重複,可能和 t e m p temp temp重複,可能和 h e a d . n e x t head.next head.next重複,也可能三個節點值相等。如果 t e m p temp temp和 h e a d head head重複,我們就知道 h e a d head head不可能加入連結串列,就改變 t e m p temp temp指向 h e a d head hea - 原連結串列頭節點的特殊處理:因為頭節點沒有 t e m p temp temp,因此我給原連結串列加上一個值為 h e a d . v a l − 1 head.val-1 head.val−1的節點作為新頭節點,然後令 t e m p temp temp指向新的頭節點,這樣可以判斷 h e a d head head是否重複。
- 原連結串列尾節點的特殊處理:當退出迴圈後,說明已經到了連結串列的結尾。此時有兩種可能:
① h e a d = = n u l l head == null head==null: t e m p temp temp指向最後一位, h e a d head head為空。那麼前面找到的連結串列就是最終結果,因為我們不考慮 t e m p temp temp,僅考慮 h e a d head head。
② h e a d . n e x t = = n u l l head.next == null head.next==null: t e m p temp temp指向連結串列的倒數第二個元素, h e a d head head指向連結串列的最後一個元素。此時如果兩個節點值相等,前面找到的連結串列就是最終結果;如果兩個節點的值不相等,那麼需要將 h e a d head head加入連結串列。 - 新的頭節點:新的頭節點有可能不存在,此時所有的元素都重複。
①如何確定新連結串列的頭節點?如果存在,即為第一個不重複的元素值。此時即體現出了將 n e w H e a d newHead newHead的初始值設為 h e a d . v a l u e − 1 head.value-1 head.value−1的原因:保證這個值是唯一的。當找到一個不重複元素,如果此時 n e w H e a d newHead newHead的值是 h e a d . v a l u e − 1 head.value-1 head.value−1,我們就知道這個元素應該作為新連結串列的頭節點。
②處理尾節點時,要記住此時頭節點可能為空。
- JAVA實現
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null) return head;
ListNode temp = new ListNode(head.val-1); //在最前面新增一個頭
temp.next = head;
int value = head.val; //當head改變,head.val也會變,因此先儲存成常量
ListNode newHead = new ListNode(value-1);
ListNode hold = newHead;
//比較三個連續的數,temp, head, head.next
//iff temp.val<head.val<head.next.val, head可以保留在連結串列中
//if temp.val == head.val, 說明head不能留,將temp和head分別後移一位
//if head.val == temp.val, 說明head和temp都不能留,將temp指向head.next,head指向temp.next
while(temp!=null && head!=null && head.next!=null) {
if(head.val > temp.val && head.val < head.next.val) {
if(newHead.val == value-1) {
newHead = head;
hold = newHead;
}
else {
hold.next = head;
hold = hold.next;
}
temp = head;
head = head.next;
}
else {
if(temp.val == head.val) temp = head;
else if(head.val == head.next.val) temp = head.next;
head = temp.next;
}
}
if(head == null) { //temp是最後一位,head是空
if(newHead.val == value-1) return head; //沒有滿足條件的
else {
hold.next = head;
return newHead;
}
}
//temp是倒數第二位,head是最後一位的情況
if(temp.val != head.val) { //值不相等,新增head
if(newHead.val == value-1) return head;
else hold.next = head;
}
else { //值相等
temp = head.next;
if(newHead.val == value-1) return temp;
else hold.next = temp;
}
return newHead;
}
}