刪除排序連結串列中的重複元素 II(Remove-Duplicates-From-Sorted-List-II)
題幹如下:
給定一個排序連結串列,刪除所有含有重複數字的節點,只保留原始連結串列中 沒有重複出現 的數字。
示例 1:
輸入: 1->2->3->3->4->4->5
輸出: 1->2->5
示例 2:
輸入: 1->1->1->2->3
輸出: 2->3
這題是上一篇 讓我們一起啃演算法—-刪除排序連結串列中的重複元素 的進階版。在上一篇中,我們刪掉了重複的其他元素,僅保留一個元素,例如: 1 -> 2 -> 2 -> 3 變成 1 -> 2 -> 3。這題,則需要將僅保留的一個元素也刪掉,例如: 1 -> 2 -> 2 -> 3 變成 1 -> 3。
解題思路
借上一篇的思路,我們需要在 current 指標基礎上再多準備一個前置指標 pre 和一個有效值指標 really。really 指標始終指向有效連結串列的尾部,pre 指標指向 current 的前置節點,因為我們需要比較當前節點 current 的值是否和前置節點、後置節點的值相等,在單向連結串列中,後置節點很容易獲取,即 current.next,但是前置節點不能很容易獲取到,需要用 pre 記錄。
初始化:由於需要一個前置節點,當 current 為連結串列的頭節點 head 時前置節點其實是不存在的,為了方便後續的邏輯,我們需要設定一個初始節點 origin,使 pre、really 指向 origin,current 指向 head。
判斷 current 的 val 與 current.next 的 val 和 pre 的 val 是否相等,相等的話,則 pre 指向 current, current 指向 current.next,如果不相等,則 really.next 指向 current,really 指向 current,同時 pre 指向 current,current 指向 current.next,大致思路如上。但是這裡有個注意事項:
按照上面的邏輯,pre 指向 current 後,需要將 pre.next 置為空,例如連結串列為: 1 —-> 2 —-> 2,如果不把 節點1 與 節點2 的連線斷開,後續返回的 origin.Next 連結串列結構為: 1 —-> 2 —-> 2 仔細體會一下!
流程圖如下:
程式碼實現
GO語言實現
func deleteDuplicates(head *ListNode) *ListNode {
origin := &ListNode{Val:0}
current := head
pre := origin
really := origin
for current != nil {
// 因為新引入了一個初始節點,防止和原始連結串列的第一個節點衝突,比如第一個節點剛好 Val 也為 0
// 那麼單純 current.Val != pre.Val 判斷是不夠的,需要加入 pre == origin 這個判斷
if (pre == origin || current.Val != pre.Val) && (current.Next == nil || current.Val != current.Next.Val) {
really.Next = current
really = current
}
pre = current
current = current.Next
// 這裡需要將 pre 和 current 之間的連線斷開,例如連結串列為: 1---->2---->2,
// 如果不把 節點1 與 節點2 的連線斷開,後續返回的 origin.Next 連結串列結構為: 1---->2---->2 仔細體會一下!
pre.Next = nil
}
return origin.Next
}
總結
每天進步一點點,加油!
演算法教程專案,每天更新一題,點個 star 支援一下呀:
github.com/wx-satellite/learning-a...
本作品採用《CC 協議》,轉載必須註明作者和本文連結