1. 程式人生 > 其它 >力扣LeetCode #82 刪除排序連結串列II(DeleteDuplicates)

力扣LeetCode #82 刪除排序連結串列II(DeleteDuplicates)

技術標籤:連結串列資料結構java演算法力扣

- 題目描述

給定一個排序連結串列,刪除所有含有重複數字的節點,只保留原始連結串列中沒有重複出現的數字。

來源: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
    temp
    h e a d head head,令 h e a d = t e m p . n e x t head = temp.next head=temp.next。然後比較 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 temp.val,head.val,head.next.val。注意我們比較這三個數,僅僅是為了確定head能否加入新連結串列 t e m p temp 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
    temp.val<head.val<head.next.val
    ,說明 h e a d head head沒有重複,可以加入新連結串列。
    ②如果不滿足,說明 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
    d
    h e a d head head指向 h e a d . n e x t head.next head.next,然後同樣判斷 h e a d head head;如果是 h e a d head head h e a d . n e x t head.next head.next重複,說明這兩個元素都不可能加入連結串列,因此需要判斷的是 h e a d . n e x t . n e x t head.next.next head.next.next,因此令 h e a d head head指向 h e a d . n e x t . n e x t head.next.next head.next.next,而 t e m p temp temp仍然指向新 h e a d head head的前一位,即改變之前的 h e a d . n e x t head.next head.next
  • 原連結串列頭節點的特殊處理:因為頭節點沒有 t e m p temp temp,因此我給原連結串列加上一個值為 h e a d . v a l − 1 head.val-1 head.val1的節點作為新頭節點,然後令 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.value1的原因:保證這個值是唯一的。當找到一個不重複元素,如果此時 n e w H e a d newHead newHead的值是 h e a d . v a l u e − 1 head.value-1 head.value1,我們就知道這個元素應該作為新連結串列的頭節點。
    ②處理尾節點時,要記住此時頭節點可能為空。

- 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;
    }
}