單向鏈表的反轉是一個非常常見的鏈表類面試題,我在刷leetcode的過程中,發現了有許多鏈表題目的解法,都是以反轉鏈表為基礎進行的。所以我覺得有必要記錄一下。
首先先用一張圖來理解單鏈表的反轉。
image
image
單鏈表的反轉,就如上圖一樣,而單鏈表的反轉也有幾種方式,今天我主要是想記錄我用得最頻繁的迭代的方式。
先來看一下鏈表節點的定義:
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
這就是最基礎的一個鏈表節點,而反轉鏈表的代碼,其實非常的短,關鍵點就在于理解這幾行代碼究竟讓鏈表產生了什么變化。
public ListNode reverseList(ListNode head) {
ListNode next = null;
ListNode pre = null
while (head != null) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
我們可以看到四行代碼:
next = head.next; // 1
head.next = pre; // 2
pre = head; // 3
head = next; // 4
第一行代碼:next = head.next;
將head.next賦值給next變量,也就是說next指向了節點2,先將節點2保存起來。
第二行代碼: head.next = pre;
將pre變量賦值給了head.next,即節點1指向了null。
第三行代碼: pre = head;
將head賦值給了pre,即pre指向節點1,將節點1設為“上一個節點”。
第四行代碼:head = next;
將next賦值給head,即head指向了節點2。將節點2設置為“頭結點”。
一次循環的具體過程就是這樣。
所以總結一下單鏈表的反轉:
- 保存當前頭結點的下個節點。
- 將當前頭結點的下一個節點指向“上一個節點”,這一步是實現了反轉。
- 將當前頭結點設置為“上一個節點”。
- 將保存的下一個節點設置為頭結點。
這樣說起來確實有點拗口,但是我推薦大家在做鏈表類題目和理解鏈表的具體行為時,用一張紙和筆來輔助自己寫寫畫畫,相信很快你就會弄懂鏈表的具體思路的。