[每日一題] 第二題:反轉連結串列

DRose發表於2020-07-04

定義一個函式,輸入一個連結串列的頭節點,反轉該連結串列並輸出反轉後連結串列的頭節點。

示例:

輸入: 1->2->3->4->5->NULL

輸出: 5->4->3->2->1->NULL

限制:

0 <= 節點個數 <= 5000

利用外部空間

先申請一個動態擴容的陣列或者容器,比如 ArrayList這樣的,

然後不斷遍歷連結串列,將連結串列中的元素新增到這個容器中。

再利用容器自身的 API,反轉整個容器,這樣就達到反轉的效果了。

最後同時遍歷容器和連結串列,將連結串列的值改為容器的值。

因為此時容器的值為 5 4 3 2 1

連結串列按照這個順序重新被設定一遍,就達到要求了。

空間複雜度

O(N)

雙指標法

演算法思想

我們申請兩個指標,一個指標叫 pre,最初指向 NULL。

第二個指標 cur 指向 head,然後不斷遍歷 cur

每次迭代 cur,都將 curnext 指向 pre,然後 precur 前進一位。

都迭代完了(cur 變成 null 了),pre 就是最後一個節點了。

程式碼

class Solution {
    public ListNode reverseList(ListNode head) {
        //申請節點,pre和 cur,pre指向null
        ListNode pre = null;
        ListNode cur = head;
        ListNode tmp = null;
        while(cur!=null) {
            //記錄當前節點的下一個節點
            tmp = cur.next;
            //然後將當前節點指向pre
            cur.next = pre;
            //pre和cur節點都前進一位
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

個人理解

從頭遍歷連結串列,修改每個節點的 next 指向的值。

那麼一個節點的新的 next 值是什麼呢,是它的前一個節點,那麼我們把它儲存起來即可,用的時候再取出來該值,所以我們定義了 pre 節點。

那麼我們應該什麼時候給當前節點的 next 節點賦值呢?

我們不能直接執行下面的程式碼 head.next = pre;,這樣是不可以的,形成閉環了。

所以我們有個臨時變數 tmp,用來儲存當前節點的 next 的值,首先將 head.next 值取出來,然後將 head.next 賦值為 pre,再將 tmp 值賦值給 head,這樣我們就下一層迴圈了。最終獲取最後一個節點,就是反轉連結串列的第一個節點,那能否透過 head 節點獲取這最後一集個節點呢,因為我們的 head 節點是最後一個節點的 next 值,為 null,所以我們取 head.pre 的值就可以了。

上面的程式碼用 cur 來代替 head

遞迴法

演算法思想

遞迴的兩個條件:

  1. 終止條件是當前節點或者下一個節點==null

  2. 在函式內部,改變節點的指向,也就是 head 的下一個節點指向 head 遞迴函式那句


head.next.next = head

程式碼

class Solution {
    public ListNode reverseList(ListNode head) {
        //遞迴終止條件是當前為空,或者下一個節點為空
        if(head==null || head.next==null) {
            return head;
        }
        //這裡的cur就是最後一個節點
        ListNode cur = reverseList(head.next);
        //這裡請配合動畫演示理解
        //如果連結串列是 1->2->3->4->5,那麼此時的cur就是5
        //而head是4,head的下一個是5,下下一個是空
        //所以head.next.next 就是5->4
        head.next.next = head;
        //防止連結串列迴圈,需要將head.next設定為空
        head.next = null;
        //每層遞迴函式都返回cur,也就是最後一個節點
        return cur;
    }
}

個人理解

終止條件為什麼有兩個?

分別對應著兩種情況:

  1. 連結串列為空,需要判斷 head==null
  2. 正常連結串列,需要判斷 head.next==null

head.next.next = head 怎麼理解?**

head.next 是當前節點的下一個節點,這個節點的 next 值就是反過來嘛,就是 head

head.next = null 是什麼意思?**

為了防止閉環。

為什麼會返回 cur?

因為 cur 是最後一層遞迴返回的值,也就是最後一個節點,也是反轉連結串列的第一個節點,所以我們返回這個節點即可。

作者:wang_ni_ma
連結:leetcode-cn.com/problems/fan-zhuan...
來源:力扣(LeetCode)

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章