題目:反轉連結串列
反轉一個單連結串列。
複製程式碼
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
進階:
你可以迭代或遞迴地反轉連結串列。你能否用兩種方法解決這道題?
複製程式碼
思考:
首先用遞迴來解決。
如果傳入的節點(head)為null或該節點的next(head.next)為null,則返回該節點。
否則遞迴呼叫自身將下一個節點傳入(head.next)。
再將當前方法中傳入的節點和其後一個節點反轉。
複製程式碼
實現:
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
複製程式碼
理解:
①處兩行程式碼完成了將傳入的head節點與head.next反轉。 ②處首先判斷傳入的head節點以及下一個節點head.next是否null,為null就直接返回head節點。
通過不斷的遞迴呼叫reverseList方法,直至傳入的節點為連結串列尾節點時head.next才會為null,直接返回尾節點。
所以newHead節點即為原來連結串列尾節點,反轉後的頭節點。
如果傳入的節點head.next不為null,就是說沒到尾節點,就將head節點與head.next節點反轉。
最終會從遞迴呼叫的最裡層開始,將最後一個節點和倒數第二個節點反轉,再將倒數第二個節點和倒數第三個節點反轉...... 返回結果是newHead節點,就是新的頭節點。
再思考:
首先用迭代法來解決。
用三個指標,head,p,q分別指向頭節點,前一個節點和後一個節點。
然後迴圈每次反轉p與q節點,反轉後將q後移,一直到q為null即連結串列尾部位置。
複製程式碼
實現:
public class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode p = head;
ListNode q = head.next;
while (q != null) {
p.next = q.next;
q.next = head;
head = q;
q = p.next;
}
return head;
}
}
複製程式碼
理解:
如下圖所示,主要是while迴圈中,用三個指標反轉節點,每次反轉後記得修改head的位置和將q向後移。最終head為反轉後列表的頭節點。