天天看點

Leetcode No.82 删除排序連結清單中的重複元素 II

題目描述

存在一個按升序排列的連結清單,給你這個連結清單的頭節點 head ,請你删除連結清單中所有存在數字重複情況的節點,隻保留原始連結清單中 沒有重複出現 的數字。

傳回同樣按升序排列的結果連結清單。

示例 1:

輸入:head = [1,2,3,3,4,4,5]

輸出:[1,2,5]

示例 2:

輸入:head = [1,1,1,2,3]

輸出:[2,3]

提示:

連結清單中節點數目在範圍 [0, 300] 内

-100 <= Node.val <= 100

題目資料保證連結清單已經按升序排列

解題思路一

掃描一次連結清單,統計數字在連結清單中出現的次數,再次周遊連結清單,當節點的值出現的次數大于等于2時,将該節點删除

import utils.ListNode;
import java.util.HashMap;
public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode newHead=head;
        HashMap<Integer,Integer> map=new HashMap();
        while(head!=null){
            int value=head.val;
            if(map.get(value)==null){
                map.put(value,1);
            }else{
                map.put(value,map.get(value)+1);
            }
            head=head.next;
        }
        ListNode sentinel=new ListNode(0);
        sentinel.next=newHead;
        ListNode pre=sentinel,cur=newHead;
        while(cur!=null){
            if(map.get(cur.val)>=2){
                pre.next=cur.next;
                cur=cur.next;
            }else{
                pre=pre.next;
                cur=cur.next;
            }
        }
        return sentinel.next;
    }
    public static void main(String[] args) {
        ListNode head=new ListNode(1);
        ListNode node2=new ListNode(1);
        head.next=node2;
        ListNode node3=new ListNode(2);
        node2.next=node3;
        node3.next=null;
        Solution solution=new Solution();
        solution.deleteDuplicates(head);
    }
}           

複制

複雜度分析

時間複雜度:O(n),其中 n 是連結清單的長度。

空間複雜度:O(n),其中 n 是連結清單的長度。

解題思路二

由于給定的連結清單是排好序的,是以重複的元素在連結清單中出現的位置是連續的,是以我們隻需要對連結清單進行一次周遊,就可以删除重複的元素。由于連結清單的頭節點可能會被删除,是以我們需要額外使用一個哨兵節點(sentinel node)指向連結清單的頭節點。

具體地,我們從指針 cur 指向連結清單的啞節點,随後開始對連結清單進行周遊。如果目前 cur.next 與 cur.next.next 對應的元素相同,那麼我們就需要将 cur.next 以及所有後面擁有相同元素值的連結清單節點全部删除。我們記下這個元素值 x,随後不斷将 cur.next 從連結清單中移除,直到 cur.next 為空節點或者其元素值不等于 x 為止。此時,我們将連結清單中所有元素值為 x 的節點全部删除。

如果目前cur.next 與cur.next.next 對應的元素不相同,那麼說明連結清單中隻有一個元素值為 cur.next 的節點,那麼我們就可以将cur 指向 cur.next。

當周遊完整個連結清單之後,我們傳回連結清單的的哨兵節點的下一個節點 sentinel.next 即可。

細節

需要注意cur.next 以及 cur.next.next 可能為空節點,如果不加以判斷,可能會産生運作錯誤。

public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head==null){
            return null;
        }
        ListNode sentinel=new ListNode(0,head);
        ListNode cur=sentinel;
        while(cur.next!=null&&cur.next.next!=null){
            if(cur.next.val==cur.next.next.val){
                int x=cur.next.val;
                while(cur.next!=null&&cur.next.val==x){
                    cur.next=cur.next.next;
                }
            }else{
                cur=cur.next;
            }
        }
        return sentinel.next;
    }

    public static void main(String[] args) {
        ListNode head=new ListNode(1);
        ListNode node2=new ListNode(1);
        head.next=node2;
        ListNode node3=new ListNode(2);
        node2.next=node3;
        node3.next=null;
        Solution solution=new Solution();
        solution.deleteDuplicates(head);
    }
}           

複制

複雜度分析

時間複雜度:O(n),其中 n 是連結清單的長度。

空間複雜度:O(1)。