題目:輸入兩個遞增排序的鏈表,合並這兩個鏈表並使新鏈表中的結點仍然是按照遞增排序的。例如下圖中的鏈表1和鏈表2,則合並之后的升序鏈表如鏈表3所示。 |
鏈表結點定義如下:
struct ListNode { int m_nValue; ListNode *m_pNext; };
注:鏈表1和鏈表2是兩個遞增排序的鏈表,合並這兩個鏈表得到升序鏈表為鏈表3.
首先分析合並兩個鏈表的過程。我們的分析從合並兩個鏈表的頭結點開始。鏈表1的頭結點的值小於鏈表2的頭結點的值,因此鏈表1的頭結點將是合並后鏈表的頭結點。如下圖所示。
- 鏈表1的頭結點的值小於鏈表2的頭結點的值,因此鏈表1的頭結點是合並后鏈表的頭結點。
- 在剩余的結點中,鏈表2的頭結點的值小於鏈表1的頭結點的值,因此鏈表2的頭結點是剩余結點的頭結點,把這個結點和之前已經合並好的鏈表的尾結點鏈接起來。
繼續合並兩個鏈表中剩余的結點(圖中虛線框所示)。在兩個鏈表中剩下的結點依然是排序的,因此合並這兩個鏈表的步驟和前面的步驟是一樣的。我們還是比較兩個頭結點的值。此時鏈表2的頭結點的值小於鏈表1的頭結點的值,因此鏈表2的頭結點的值將是合並剩余結點得到的鏈表的頭結點。我們把這個結點和前面合並鏈表時得到的鏈表的尾結點(值為1的結點)鏈接起來,如圖所示。
當我們得到兩個鏈表中值較小的頭結點並把它連接到已經合並的鏈表之后,兩個鏈表剩余的結點依然是排序的,因此合並的步驟和之前的步驟是一樣的。這就是典型的遞歸的過程,可以定義遞歸函數來完成者以合並過程。
每當代碼試圖訪問空指針指向的內存時程序就會崩潰,從而導致魯棒性問題。在本題中,當第一個鏈表是空鏈表,也就是它的頭結點是一個空指針時,那么把它和第二個鏈表合並,顯然合並的結果是第二個鏈表。同樣,當輸入的第二個鏈表的頭結點是空指針時,我們把它和第一個鏈表合並得到的結果就是第一個鏈表。如果兩個鏈表都是空鏈表,合並的結果是得到一個空鏈表。
實現代碼如下:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { if(pHead1 == NULL) return pHead2; else if(pHead2 == NULL) return pHead1; ListNode* pMergedHead = NULL; if(pHead1->m_nValue < pHead2->m_nValue) { pMergedHead = pHead1; pMergedHead->m_pNext = Merge(pHead1->m_pNext, pHead2); } else { pMergedHead = pHead2; pMergedHead->m_pNext = Merge(pHead1, pHead2->m_pNext); } return pMergedHead; }
