Day 2 刪除無序鏈表中的重復(fù)節(jié)點(diǎn)

算法 Day2

刪除無序鏈表中的重復(fù)節(jié)點(diǎn),保留一個

給定一個無序單向鏈表的頭節(jié)點(diǎn),刪除內(nèi)部的重復(fù)節(jié)點(diǎn),使其內(nèi)部節(jié)點(diǎn)元素不重復(fù)。(值相等即認(rèn)為重復(fù))

解法一 使用Map數(shù)據(jù)結(jié)構(gòu),以空間換時間

使用Map數(shù)據(jù)結(jié)構(gòu),遍歷鏈表,以鏈表節(jié)點(diǎn)為key,節(jié)點(diǎn)出現(xiàn)次數(shù)為value,在存儲次數(shù)時,僅第一次出現(xiàn)時把value置為1,后續(xù)進(jìn)入如果已經(jīng)發(fā)現(xiàn)Map中存儲的次數(shù)為1,那么直接把該節(jié)點(diǎn)刪除。額外需要注意的時,利用Hash類的數(shù)據(jù)結(jié)構(gòu)時,我們應(yīng)該重寫equals和hashcode方法,用內(nèi)部的value作為判斷標(biāo)準(zhǔn)。
考慮到是不重復(fù)的節(jié)點(diǎn)及Map數(shù)據(jù)結(jié)構(gòu),同時我們只需要判斷節(jié)點(diǎn)是不是在集合中,也就是并不需要真正存儲次數(shù),而HashSet內(nèi)部是通過HashMap來實(shí)現(xiàn)的,因此可以選擇使用HashSet。

static void removeRepeatNode(LinkNode head){
    if(head != null){
        HashSet<LinkNode> hashSet = new HashSet<>();
        LinkNode pre = head;
        LinkNode cur = head.mNext;
        //由于當(dāng)前節(jié)點(diǎn)從頭節(jié)點(diǎn)下一個開始,因此記錄第一個節(jié)點(diǎn)的值
        hashSet.add(pre);
        while(cur != null){
                if(hashSet.contains(cur)){
                    // 需要移除
                    cur = cur.mNext;
                    pre.mNext = cur;
                }else{
                    pre = cur;
                    // 如果沒有這個節(jié)點(diǎn),那么需要添加該節(jié)點(diǎn)
                    hashSet.add(cur);
                    cur = cur.mNext;
                }
        }
    }
}

static class LinkNode{
    int mValue;
    LinkNode mNext;

    public LinkNode(int value) {
        mValue = value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof LinkNode)) return false;

        LinkNode linkNode = (LinkNode) o;

        return mValue == linkNode.mValue;
    }

    @Override
    public int hashCode() {
        return mValue;
    }
}

容易出錯處:

1)節(jié)點(diǎn)需要重寫equals和hashcode方法

2)添加未出現(xiàn)過的節(jié)點(diǎn)時需要先添加后設(shè)置cur為下一個節(jié)點(diǎn)

復(fù)雜度分析:
需要遍歷一遍單向鏈表,因此時間復(fù)雜度O(n);空間復(fù)雜度上需要依賴一個Map數(shù)據(jù)結(jié)構(gòu),因此空間復(fù)雜度O(n)

解法二: 不使用額外的空間復(fù)雜度

從頭到尾部遍歷鏈表,每次遍歷到一個節(jié)點(diǎn),和后面所有的節(jié)點(diǎn)比較,如果兩個節(jié)點(diǎn)值相等,那么把被比較的節(jié)點(diǎn)刪除。

private static void removeRepeatNode2(LinkNode head){
    while(head != null){
        //遍歷后續(xù)所有節(jié)點(diǎn)
        LinkNode cur = head.mNext;
        LinkNode pre = head;
        while(cur != null){
            if(cur.mValue == head.mValue){// pre不變
                pre.mNext = cur.mNext;
                cur = cur.mNext;
            }else{//pre需要跟著變
               pre = cur;
               cur = cur.mNext;
            }
        }
        //繼續(xù)下一個節(jié)點(diǎn)
        head = head.mNext;
    }
}

復(fù)雜度分析:
需要遍歷整個鏈表中每個節(jié)點(diǎn),在遍歷到每個節(jié)點(diǎn)的同時,需要拿該節(jié)點(diǎn)后面所有的元素跟它比較,因此時間復(fù)雜度是O(n^2),空間復(fù)雜度O(1)

代碼

地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容