1. 程式人生 > >LeetCode-206 reverse-linked-list 反轉連結串列

LeetCode-206 reverse-linked-list 反轉連結串列

題目連結

reverse-linked-list

題意

中文題,反轉連結串列,給出連結串列頭,要求輸出一個連結串列頭,oj會遍歷以判定是否反轉。

題解

        簡單的方法是迭代,然後反向輸出。或者說利用額外空間儲存遍歷連結串列的資料,然後在構造一個連結串列頭,反向輸出額外空間儲存資料來建立一個新連結串列。但是連結串列的遍歷本來就是利用指標指向一層一層向下遍歷,並且是反向輸出,很自然能想到利用遞迴的方法。在回溯的時候輸出就可以了。但是這不是ACM,可以看到方法的返回值是一個ListNode物件,也就是要求構造出一個連結串列,並返回連結串列頭。如果在回溯的時候構造很麻煩,因為還得回溯下一個引用指向的物件。所以我們可以在原來的連結串列上進行修改。

        這裡先上一下程式碼,下面是圖解:

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

那麼首先是遞迴過程:

可以看到,在遞迴的時候,ret在等待回溯結果,等到第三層遞迴,返回最後一個節點,之前先宣告每個節點的next是null。因為反轉以後最後一個節點的next必須是null。

        接下來是回溯的過程:

可以看到,回溯過程實際上每次向上傳遞的永遠都是最後一個節點,那麼最後返回的結果就是最後一個節點了,而這也是反轉連結串列的head。那麼除了這個過程,可以看到主要做了3件事:

1.當前節點.next = null

2.下層節點.next = 當前節點

第一步的作用是防止最後一個節點的next不是null,而第二步的作用實際上是翻轉連結串列。因為遞迴的時候已經遍歷過的節點就可以刪除聯絡了,因為沒有用了。最終層層向上回溯的只是最後一個節點。但是在遞迴的時候從第一個節點開始已經完成了翻轉,第一個節點的next也變成了null。這樣,就能在不額外大量開闢空間(實際上是多了next這個物件)的情況下進行反轉操作。

Java 程式碼

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode next = head.next;
        head.next = null;
        ListNode ret = reverseList(next);
        next.next = head;
        return ret;
    }
}