【LeetCode題解】19_刪除連結串列的倒數第N個節點(Remove-Nth-Node-From-End-of-List)
阿新 • • 發佈:2018-11-23
更多 LeetCode 題解筆記可以訪問我的 github。
文章目錄
描述
給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。
示例:
給定一個連結串列: 1->2->3->4->5, 和 n = 2.
當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.
說明:
給定的 n 保證是有效的。
進階
你能嘗試使用一趟掃描實現嗎?
解法:雙指標
思路
求解這道問題等價於尋找倒數的第
個節點,然後將該節點的 next
指標執行倒數第
個節點。 為了找到倒數第
個節點,我們必須藉助一把長度可變尺子——雙指標。
具體的做法如下:
第 0 步(準備階段)
p1
和 p2
)指向虛擬頭節點;
第一步:將 p2
指標移動
步,此時,p2
指標位於第
個節點,兩個指標之間的長度為
,這就是我們的尺子;
第二步:移動我們的尺子(同時移動兩個指標),直到 p2
指標到達連結串列的尾部,此時,p1
指標的 next
引用所指向的正是倒數第
個節點;
最後,我們只需要操作 p1
指標的 next
引用,使得它指向倒數第
個節點即可實現對於倒數第
個節點的刪除操作。
Java 實現
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null || head.next == null) {
return null;
}
// 建立一個虛擬頭節點
ListNode dummy = new ListNode(-1);
dummy.next = head;
// 建立兩個指標,並將p2指標移動n步
ListNode p1 = dummy, p2 = dummy;
for (int i = 0; i < n; ++i) {
p2 = p2.next;
}
// 移動兩個指標直到p2處於連結串列尾部
while (p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
// 刪除第n個節點
// ListNode nthNode = p1.next;
p1.next = p1.next.next;
// nthNode.next = null;
return dummy.next;
}
}
// Runtime: 6 ms
// Your runtime beats 100.00 % of java submissions.
Python 實現
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
if not head or not head.next:
return None
# 建立虛擬頭節點
dummy = ListNode(-1)
dummy.next = head
# 建立兩個指標,並將指標p2移動n步
p1, p2 = dummy, dummy
for i in range(n):
p2 = p2.next
# 同時移動兩個指標,直到p2位於連結串列的尾部
while p2.next:
p1, p2 = p1.next, p2.next
# 刪除倒數第n個節點
p1.next = p1.next.next
return dummy.next
# Runtime: 36 ms
# Your runtime beats 100.00 % of python3 submissions.
複雜度分析
- 時間複雜度:
,其中
表示連結串列的長度。首先需要
次操作將
p2
指標移動到第 個節點;接著,需要 次操作將p2
指標移動到連結串列尾部,同時將p1
移動到倒數第 個節點。因此,總的時間複雜度是 的。 - 空間複雜度: