前面我們實現了幾種常見的 連結串列 ,接下來,我們來聊聊如何實現 單連結串列 的反轉。
連結串列反轉
示例:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
Input: NULL
Output: NULL
複製程式碼
我們可以通過迴圈遍歷和遞迴這兩種方式來實現連結串列的反轉。
遍歷
思路
定義三個指標,分別為prev、curr、next,然後遍歷所有node結點,並移動這三個指標,改變curr結點的next指向,指向prev結點,實現linkedList的反轉。
程式碼實現
/**
* 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 prev = null;
ListNode curr = head;
ListNode next = null;
while(curr != null){
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
}
複製程式碼
遞迴
其實遞迴的實現方式和前面迴圈的方式非常相似,前者是通過迴圈來移動指標,後者是通過遞迴來移動指標。
定義一個遞迴介面,傳入curr與prev節點作為引數,內部再將curr的作為下次遞迴呼叫的prev入參,curr.next
作為下次遞迴呼叫的curr入參。
程式碼實現
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head){
return reverseRecursively(head, null);
}
public ListNode reverseRecursively(ListNode curr, ListNode prev) {
if(curr == null){
return null;
}
if(curr.next == null){
ListNode head = curr;
curr.next = prev;
return head;
}
ListNode next1 = curr.next;
curr.next = prev;
ListNode head = reverseRecursively(next1, curr);
return head;
}
}
複製程式碼
這兩種方式的時間複雜度均為O(n),空間複雜度均為O(1)。