LeetCode演算法題

Vicali發表於2020-12-05

題目:反轉連結串列

  • 方法一:迭代
    假設存在連結串列 1 \rightarrow 2 \rightarrow 3 \rightarrow \varnothing1→2→3→∅,我們想要把它改成 \varnothing \leftarrow 1 \leftarrow 2 \leftarrow 3∅←1←2←3。

在遍歷列表時,將當前節點的 \textit{next}next 指標改為指向前一個元素。由於節點沒有引用其上一個節點,因此必須事先儲存其前一個元素。在更改引用之前,還需要另一個指標來儲存下一個節點。不要忘記在最後返回新的頭引用!

Java

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }
}

複雜度分析

時間複雜度:O(n)O(n),假設 nn 是列表的長度,時間複雜度是 O(n)O(n)。
空間複雜度:O(1)O(1)。

  • 方法二:遞迴
    遞迴版本稍微複雜一些,其關鍵在於反向工作。假設列表的其餘部分已經被反轉,現在我們應該如何反轉它前面的部分?

假設列表為:

n_{1}\rightarrow \ldots \rightarrow n_{k-1} \rightarrow n_{k} \rightarrow n_{k+1} \rightarrow \ldots \rightarrow n_{m} \rightarrow \varnothing
n
1

→…→n
k−1

→n
k

→n
k+1

→…→n
m

→∅

若從節點 n_{k+1}n
k+1

到 n_{m}n
m

已經被反轉,而我們正處於 n_{k}n
k

n_{1}\rightarrow \ldots \rightarrow n_{k-1} \rightarrow n_{k} \rightarrow n_{k+1} \leftarrow \ldots \leftarrow n_{m}
n
1

→…→n
k−1

→n
k

→n
k+1

←…←n
m

我們希望 n_{k+1}n
k+1

的下一個節點指向 n_{k}n
k

所以,n_k.\textit{next}.\textit{next} = n_{k}n
k

.next.next=n
k

要小心的是 n_{1}n
1

的下一個必須指向 \varnothing∅ 。如果你忽略了這一點,你的連結串列中可能會產生迴圈。如果使用大小為 22 的連結串列測試程式碼,則可能會捕獲此錯誤。

Java

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return p;
    }
}

複雜度分析

時間複雜度:O(n)O(n),假設 nn 是列表的長度,那麼時間複雜度為 O(n)O(n)。
空間複雜度:O(n)O(n),由於使用遞迴,將會使用隱式棧空間。遞迴深度可能會達到 nn 層。

作者:LeetCode
連結:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

相關文章