Reverse a singly linked list.
Example:
Input: 1->2->3->4->5->NULL Output: 5->4->3->2->1->NULLFollow up:
A linked list can be reversed either iteratively or recursively. Could you implement both?
迭代是從前往後依次處理,直到循環到鏈尾;而遞歸恰恰相反,首先一直迭代到鏈尾也就是遞歸基判斷的準則,然後再逐層返回處理到開頭。總結來說,鏈表翻轉操作的順序對於迭代來說是從鏈頭往鏈尾,而對於遞歸是從鏈尾往鏈頭。
迭代法: 時間複雜度O(n),空間複雜度O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head; //用來保存當前節點
ListNode prev = null; //因爲要用到前一個結點,所以使用prev結點保存
while(cur!=null){
ListNode next = cur.next; //next結點用來保存cur.next指針域
cur.next = prev; //注意順序
prev = cur;
cur = next;
}
return prev; //結束時,cur結點爲空,prev結點爲鏈表最後一個結點
}
}
遞歸法:時間複雜度O(n),空間複雜度O(n)
圖1:鏈表反轉結果
遞歸時,考慮把問題規模減小,假設我們的程序能夠正常反轉,則結果如下
反轉後,1元素並沒有任何操作,所以反轉1的next仍然指向2,接下來只要將2的next指向1,而1的next指向null即可。
/**
* 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;} //head表示鏈表爲空head.next是遞歸終止
ListNode temp = head.next;
ListNode newHead = reverseList(head.next); //前幾行用來遍歷到最後一個結點
temp.next = head; //反轉鏈表
head.next = null; //避免出現環
return newHead;
}
}