題目:輸入兩個遞增排序的鏈表,合併這兩個鏈表並使新鏈表中的結點仍然是按照遞增排序的。鏈表的結點定義如下:
struct ListNode
{
int val;
ListNode* next;
};
例如輸入如圖所示的鏈表1和鏈表2,合併之後爲鏈表3:
鏈表1:
鏈表2:
鏈表3:
這是一個經常被各公司採用的面試題。在面試過程中,最容易犯的兩個錯誤是:
- 合併出來的鏈表要麼中間斷了,要麼並沒有做到遞增排序
- 程序一旦有特殊輸入就會崩潰
首先分析合併兩個鏈表的過程:
(1)鏈表1的頭結點的值小於鏈表2的頭結點的值,因此鏈表1的頭結點是合併後的鏈表的頭結點。
(2)在剩餘的結點中,鏈表2的頭結點的值小於鏈表1的頭結點的值,因此鏈表2的頭結點是剩餘結點的頭結點,把這個結點和之前已經合併好的鏈表的尾結點連接起來。
我們繼續合併兩個鏈表中剩餘的結點,在兩個鏈表中剩餘的結點依然是排序的,因此合併這兩個鏈表的步驟和前面的步驟是一樣的。這就是典型的遞歸過程,我們可以定義遞歸函數完成這一合併過程。
注意:本題一旦引入空鏈表就會引入空指針,因此我們要對空鏈表進行單獨處理。
參考代碼如下:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL)
return pHead2;
if(pHead2 == NULL)
return pHead1;
ListNode* MergeHead = NULL;
if(pHead1->val < pHead2->val)
{
MergeHead = pHead1;
MergeHead->next = Merge(pHead1->next,pHead2);
}
else
{
MergeHead = pHead2;
MergeHead->next = Merge(pHead1,pHead2->next);
}
return MergeHead;
}