將兩個有序鏈表合併爲一個新的有序鏈表並返回。新鏈表是經過拼接給定的兩個鏈表的全部節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4算法
鑑於上個題目兩個數相加之和的總結,此次不在定義兩個臨時變量指向兩個鏈表,直接遍歷兩個鏈表
1.定義一個帶頭結點的鏈表
2.遍歷兩個鏈表l一、l2,比較兩個鏈表當前結點的值的大小,小結點直接插入結果鏈表,同時向後移動該鏈表,循環此過程直到其中一個鏈表爲NULL結束。
3.將不爲NULL的鏈表插入到結果鏈表上函數
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode res(-1); ListNode* pRes = &res; while (l1 != NULL && l2 != NULL) { if (l1->val > l2->val) { pRes->next = l2; l2 = l2->next; } else { pRes->next = l1; l1 = l1->next; } pRes = pRes->next; } if (l1 == NULL) { pRes->next = l2; } if (l2 == NULL) { pRes->next = l1; } return res.next; }
有了上一道題目優化經驗,就能夠直接省去一些思考的中間環節,直接寫出一次性滿意的代碼。
優化
合併 k 個排序鏈表,返回合併後的排序鏈表。請分析和描述算法的複雜度。
示例:
輸入:
[
1->4->5,
1->3->4,
2->6
]
輸出: 1->1->2->3->4->4->5->6code
1.合併K個鏈表就是選擇兩個先合併成一個鏈表再將合成後的鏈表與剩餘的鏈表一一合併得出最終的結果
2.合併兩個鏈表直接調用上到題目完成的函數。blog
常規思路:排序
ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode res(-1); ListNode* pRes = &res; for (size_t i = 0; i < lists.size(); i++) { pRes->next = mergeTwoLists(lists[i], pRes->next); } return res.next; }
遞歸思路:遞歸
ListNode* mergeKLists(vector<ListNode*>& lists) { int size = lists.size(); if (size == 0) { return NULL; } if (size == 1) { return lists[0]; } for (int i = 0; i < size / 2; i++) { lists[i] = mergeTwoLists(lists[i], lists[size - i - 1]); lists.pop_back(); } ListNode res(-1); res.next = mergeKLists(lists); return res.next; }
1.常規思路就是將每個鏈表逐一合併。
2.遞歸思路是將鏈表兩兩分紅一組進行合併,最終將全部的分組再次進行兩兩合併,直到合併爲一個鏈表爲止,這就是遞歸分治的思路
3.對比兩種思路:遞歸思路減小了合併的次數。
變量