leetcode 探索 鏈表 移除鏈表元素

題目

刪除鏈表中等於給定值 val 的所有節點。
示例:

輸入: 1->2->6->3->4->5->6, val = 6
輸出: 1->2->3->4->5
來源Leetcode: https://leetcode-cn.com/problems/remove-linked-list-elements/

分析

遇到這種經典的鏈表題的時候,我懵逼了,我不會。。。繞頭腦,稍微不注意就會繞進去了,就不知道指針指哪裏了。所以這題我要好好分析分析,好好記錄一下,來理解這種鏈表。

這個題目啊,要注意是刪除給定值的所有節點。注意到我加粗的地方了嗎?
我們知道刪除鏈表元素時候,只需要把前一個節點的Next指向當前節點的Next元素,從而就可以丟棄到當前要刪除的節點。所以我們要記錄上一個節點prev。
在這裏插入圖片描述
假如cur節點是要刪除的節點,那麼將prev.Next = cur.Next即可實現刪除。
在這裏插入圖片描述
但我們知道,刪除節點要注意如果刪除的是頭節點呢。我可以簡單的將head = head.Next,但如果有多個連續的呢?那麼我們可能要做一個while循環一直檢測,一直刪除。

這裏就有另外一種處理了,做一個僞頭,也就是哨兵節點。哨兵節點指向頭節點,這樣刪除頭節點就和刪除中間節點沒什麼兩樣了,就可以簡化處理邏輯。

有了哨兵節點,我們就可以pre, cur := sentinel, head。這樣當判定cur是要刪除的節點時候,pre.Next = cur.Next就完成刪除了。管你cur是頭節點還是尾結點呢?

刪除節點,我們要考慮它是不是尾結點嗎?不需要,因爲啥呢,刪除尾結點時候,尾結點的Next是nil,把它賦給prev.Next 並不會產生panic。

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeElements(head *ListNode, val int) *ListNode {
    if head == nil {
        return nil
    }
    
    sentinel := &ListNode{
        Next: head,
        Val: -1,
    }
    // pre 用於記錄上一個節點,這裏首先指向哨兵節點,cur就指向head節點
    pre, cur := sentinel, head
    
    for cur != nil {
        if cur.Val == val {
            // 如果當前節點與要刪除的一致,就把上一個節點的Next跳過當前節點,指向下一個
            pre.Next = cur.Next
        } else {
            // 這裏的pre只用做記錄上一個節點。用於要刪除的時候,切換一下指向。
            pre = cur
        }
        cur = cur.Next
    }
    
    return sentinel.Next
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章