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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章