LeetCode#19. 刪除連結串列的倒數第N個節點
阿新 • • 發佈:2020-11-22
給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。
示例:
給定一個連結串列: 1->2->3->4->5, 和 n = 2.
當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.
說明:
給定的 n 保證是有效的。
進階:
你能嘗試使用一趟掃描實現嗎?
解題思路:雙指標和滑動視窗,右指標先走n步,然後左右指標一起走。左指標一開始指向新增的一個啞節點(dummy node),它的next指標指向連結串列的頭節點。這樣一來,我們就不需要對頭節點進行特殊的判斷了。最後左指標指向倒數第 n+1 個節點,將它的 next 指向倒數第 n-1個節點。注意一個 或 兩個節點的情況。
// 方法一:雙指標+滑窗 func removeNthFromEnd(head *ListNode, n int) *ListNode { dummyHead := &ListNode{0, head} // 前後驅指標 left, right := dummyHead, head for i := 0; i < n; i++ { right = right.Next } for ; right != nil; right = right.Next { left = left.Next } left.Next = left.Next.Next return dummyHead.Next } /*時間複雜度O(L) 空間複雜度O(1)*/
其他兩種方式
//方法二:先求長度,再遍歷到倒數n+1個, 刪除 func getLength(head *ListNode) (length int) { for ; head != nil; head = head.Next { length++ } return } func removeNthFromEnd(head *ListNode, n int) *ListNode { length := getLength(head) dummy := &ListNode{0, head} cur := dummy for i := 0; i < length-n; i++ { cur = cur.Next } cur.Next = cur.Next.Next return dummy.Next } /* 時間複雜度:O(2L-n),其中 L 是連結串列的長度。 空間複雜度:O(1)。 */
// 方法三:棧實現
func removeNthFromEnd(head *ListNode, n int) *ListNode {
nodes := []*ListNode{}
dummy := &ListNode{0, head}
for node := dummy; node != nil; node = node.Next {
nodes = append(nodes, node)
}
prev := nodes[len(nodes)-1-n]
prev.Next = prev.Next.Next
return dummy.Next
}
/*
時間複雜度:O(L)
空間複雜度:O(L) 主要為棧的開銷。*/