面試題24:反轉單鏈表(解法二:遞迴法)
阿新 • • 發佈:2020-08-17
反轉單鏈表的兩種方法
今天看了帥地的第二版資料,突然發現單鏈表的反轉居然還可以用遞迴來做,太妙了吧!
直接上程式碼,目前只有C++版的(用指標寫連結串列它不香嗎?):
// 遞迴法反轉單鏈表 ListNode* reverseListPlus(ListNode* pHead){ if(pHead == nullptr || pHead->next == nullptr) return pHead; ListNode* reverseNode = reverseListPlus(pHead->next); pHead->next->next = pHead; pHead->next = nullptr; return reverseNode; } int main() { ListNode* pNode1 = createListNode(1); ListNode* pNode2 = createListNode(2); ListNode* pNode3 = createListNode(3); ListNode* pNode4 = createListNode(4); ListNode* pNode5 = createListNode(5); connectListNodes(pNode1, pNode2); connectListNodes(pNode2, pNode3); connectListNodes(pNode3, pNode4); connectListNodes(pNode4, pNode5); PrintListNodes(pNode1); // 遞迴法反轉連結串列 reverseListPlus(reverseList(pNode1)); // 測試反轉是否成功 PrintListNodes(pNode5); return 0; }
程式碼解釋:
1、ListNode* reverseNode = reverseListPlus(pHead->next);
-
遞迴法的目的是要返回一個新的頭節點,這個新的頭節點是原來連結串列的尾節點。
-
遞迴是方法自己呼叫自己,棧的特性是先進後出、後進先出。所以這段程式碼的作用是不斷的去壓棧。
2、pHead->next->next = pHead;
把當前節點指向的下一個節點的指向變為自己。(不要慌,這段程式碼的解釋,下面有圖有真相);
3、pHead->next = nullptr;
當前節點指向的下一個節點變為空。
是不是看了上面的解釋還有點不理解,別急,我第一次看這段程式碼的時候也是懵逼的(內心wc:這寫了個啥,怎麼就反轉連結串列了),要理解這段程式碼首先,我們得去壓幾個棧:
ListNode* reverseNode = reverseListPlus(pHead->next);
這段程式碼會執行四次,壓棧四次,如圖:
if(pHead == nullptr || pHead->next == nullptr) return pHead;
這段程式碼會讓 reverseListPlus(pHead(4)) 發生彈棧,然而連結串列沒有發生任何變化。。。方法繼續執行。
接著 reverseRecursion(head(3)) 彈棧執行下面這段程式碼
head.next.next = head;
head.next = null;
reverseRecursion(head(3))
持續到最後reverseRecursion(head(1))出棧:連結串列反轉完成,撒花
head.next.next = head;
head.next = null;