給你一個鏈表,刪除鏈表的倒數第 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:
- 根據分析1,說明需要找到刪除節點的位置
- 根據分析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,說明可以采用快慢指針,先讓快指針指向n節點的位置,然后同時讓快慢指針移動,直到快指針指向鏈表末尾.
- 根據分析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
考察要點:
- 鏈表
- 雙指針