初級算法-鏈表-刪除鏈表的倒數第N個節點

給你一個鏈表,刪除鏈表的倒數第 n 個結點,并且返回鏈表的頭結點。
提示:

鏈表中結點的數目為 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

進階:你能嘗試使用一趟掃描實現嗎?
刪除鏈表的倒數第N個節點.jpg
摘一個示例做個說明.
示例 1:
如圖
輸入:head = [1,2,3,4,5], n = 2
輸出:[1,2,3,5]
條件分析:
  1. 鏈表刪除某一項 -> 需要找到刪除的位置
  2. 返回鏈表的頭結點 -> 返回刪除后的鏈表
解決思路1:
  1. 根據分析1,說明需要找到刪除節點的位置
  2. 根據分析2,說明需要知道鏈表的長度
先判斷刪除的是否是頭節點,然后通過循環找到需要刪除的位置,再進行循環操作指到需要刪除的節點,讓節點指向待刪除節點的下一個節點.
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
    let index = nodeLength(head) - n
    
    if index == 0 {
        // 刪除第一個
        return head?.next
    }
    
    var newHead = head
    for _ in 0 ..< index - 1 {
        newHead = newHead?.next
    }
    newHead?.next = newHead?.next?.next
    
    return head;
}

func nodeLength(_ head: ListNode?) -> Int{
    
    if head == nil {
        return 0
    }
    // 通過遞歸獲取長度
    return nodeLength(head?.next) + 1
}
刪除鏈表的倒數第N個節點 1 提交結果.jpg
解決思路2:
  1. 根據分析1,說明可以采用快慢指針,先讓快指針指向n節點的位置,然后同時讓快慢指針移動,直到快指針指向鏈表末尾.
  2. 根據分析2,此時慢指針指向的就是倒數第n個節點,直接讓慢指針指向下一個節點即可.
創建一個節點,然后讓該節點指向鏈表頭節點.然后定義快慢指針,讓快指針先移動n位,然后保持快慢指針相差n,當快指針指向末尾的時候,慢指針指向倒數第n個節點.最后讓慢指針指向刪除的下一個節點即可.
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
    let resultHead = ListNode(-1)
    resultHead.next = head
    var fast = resultHead
    var slow = resultHead
    
    for _ in 0 ..< n {
        // 先讓快指針指向第n個節點
        fast = fast.next!
    }
    
    while fast.next != nil {
        // 讓快慢指針同時指向下一個節點,直到鏈表結束,此時快慢指針相差n個
        fast = fast.next!
        slow = slow.next!
    }
    // 讓慢指針指向下一個節點即可
    slow.next = slow.next!.next
    
    return resultHead.next
}
刪除鏈表的倒數第N個節點 2提交結果.jpg
解決思路3:

解決思路2優化,還是快慢指針,還是快指針先走,不同與思路2先循環,采用變量判斷是否需要讓慢指針移動.

一趟掃描,通過哨兵,實現刪除.
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
    let resultHead = ListNode(-1)
    resultHead.next = head
    var fast = resultHead, slow = resultHead, index = 0
    while fast.next != nil {
        // 讓快慢指針同時指向下一個節點,直到鏈表結束,此時快慢指針相差n個
        fast = fast.next!
        index += 1
        if index > n {
            slow = slow.next!
        }
    }
    // 讓慢指針指向下一個節點即可
    slow.next = slow.next!.next
    
    return resultHead.next
}
刪除鏈表的倒數第N個節點 3提交結果.jpg

測試用例:

let endNode = ListNode.init(0)
let fourNode = ListNode.init(1)
fourNode.next = endNode
let threeNode = ListNode.init(2)
threeNode.next = fourNode
let secondNode = ListNode.init(3)
secondNode.next = threeNode
let firstNode = ListNode.init(4)
firstNode.next = secondNode
let headNode = ListNode.init(5)
headNode.next = firstNode

考察要點:

  • 鏈表
  • 雙指針
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容