LeetCode-206 reverse-linked-list 反轉連結串列
阿新 • • 發佈:2018-11-07
題目連結
題意
中文題,反轉連結串列,給出連結串列頭,要求輸出一個連結串列頭,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;
}
}