面經------單向鏈表反轉
問題描述
現定義瞭如下的ListNode結構, 要求對整個List進行反轉。
//Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
遞歸解法
遞歸的思路是從鏈表的最後一個Node開始反轉,創建一個newHead指向最後一個Node(cur),head指向newHead的前一個Node, 然後反轉cur和head,如此逐步向前。
詳細解釋如下。
首先指針H迭代到底如下圖所示,並且設置一個新的指針newHead作爲反轉後的鏈表的頭。由於整個鏈表翻轉之後的頭就是最後一個數,所以整個過程newHead指針一直指向最後一個Node。
然後H指針逐層返回的時候如下圖,將H指向的地址賦值給nextNode->next指針,並且一定要記得讓H->next =NULL,也就是斷開現在指針的鏈接,否則新的鏈表形成了環,下一層nextNode->next賦值的時候會覆蓋後續的值。程序中的nextNode指針即爲上一層返回的H->next.
第二次返回nextNode後如下圖。
逐層返回:
返回到頭後如下圖:
代碼如下:
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode nextNode = head.next;
ListNode newHead = reverseList(nextNode);
nextNode.next = head;
head.next = null;
return newHead;
}
非遞歸解法
非遞歸的方法與遞歸方法相反,它是從前往後順序處理Node的。
首先設置兩個新Node,P (curr)和 newH(prev)。
然後依次將舊鏈表上每一項添加在新鏈表的後面,然後新鏈表的頭指針NewH移向新的鏈表頭,如下圖所示。此處需要注意,不可以上來立即將上圖中P->next直接指向NewH,這樣存放2的地址就會被丟棄,後續鏈表保存的數據也隨之無法訪問。而是應該設置一個臨時指針nextTemp,先暫時指向P->next指向的地址空間,保存原鏈表後續數據。然後再讓P->next指向NewH,最後P=nextTemp就可以取回原鏈表的數據了,所有循環訪問也可以繼續展開下去。
指針繼續向後移動,直到P指針指向NULL停止迭代。
最後一步
代碼如下:
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
僅用於個人的學習理解,如需轉載,請標明出處:
https://blog.csdn.net/sc19951007/article/details/83613598