題目
定義一個函數,輸入一個鏈表的頭節點,反轉該鏈表並輸出反轉後鏈表的頭節點。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
思路
雙指針法:定義兩個指針cur和pre,進行局部翻轉,然後向前移動。
- 定義兩個指針: prepre 和 curcur ;prepre 在前 curcur 在後。
- 每次讓 prepre 的 nextnext 指向 curcur ,實現一次局部反轉
- 局部反轉完成之後, prepre 和 curcur 同時往前移動一個位置
- 循環上述過程,直至 prepre 到達鏈表尾部
遞歸法:一直遞歸進行對head.next的翻轉。
- 使用遞歸函數,一直遞歸到鏈表的最後一個結點,該結點就是反轉後的頭結點,記作 ret 。
- 每次函數在返回的過程中,讓當前結點的下一個結點的 next指針指向當前節點。
- 讓當前結點的 next指針指向 NULL,從而實現從鏈表尾部開始的局部反轉
- 當遞歸函數全部出棧後,鏈表反轉完成。
代碼
public static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
/**
* 遞歸法
* @param head 頭結點
* @return
*/
public static ListNode reverseList1(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode re = reverseList1(head.next);//遞歸
head.next.next = head;
head.next = null;
return re;
}
/**
* 雙指針法
* @param head 頭結點
* @return
*/
public static ListNode reverseList2(ListNode head) {
ListNode cur = null;
ListNode pre = head;
while (pre != null){
//pre與cur進行局部翻轉
ListNode tempnode = pre.next;
pre.next = cur;
cur = pre;
pre = tempnode;
}
return cur;
}