演算法設計課第二週作業
阿新 • • 發佈:2018-12-10
Merge k Sorted Lists
題目描述
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
實驗思路
- 因為是已經是排好序的陣列,所以沒必要遍歷一遍生成一個新的陣列再進行遞迴排序,這樣不僅浪費記憶體,也浪費時間。
- 所以採用分治的思想,把這個vector中的lists分為兩半,再進行排序。
- 遞迴步驟2。
- 合併並排序。 ## 程式碼展示
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {
}
};
class Solution {
public:
ListNode* mergeLists(ListNode* left, ListNode *right){
//如果左邊的連結串列為空,則返回右邊的連結串列
if(!left){
return right;
}
//如果右邊的連結串列為空,則返回左邊的連結串列
if(!right){
return left;
}
//變數ptr用於記錄最後返回的合併後的連結串列的頭
ListNode* ptr = NULL;
//變數pptr用於整合兩個連結串列
ListNode** pptr = &ptr;
while(left || right){
//如果左邊的連結串列不為空且大於右邊的連結串列,則把該節點從原連結串列中取出,將NULL賦值給該節點的next指標其實就相當於把它從原來的鏈中“打斷”
if((left && !right) || (left && (left->val < right->val))){
*pptr = left;
ListNode* temp = left->next;
left->next = NULL;
ptr = &((*pptr)->next);
left = temp;
}else{
*pptr = right;
ListNode* temp = right->next;
right->next = NULL;
pptr = &((*pptr)->next);
right = temp;
}
}
return ptr;
}
//將連結串列陣列遞迴分為左右兩半
ListNode* mergeK(const vector<ListNode*>::iterator begin, const vector<ListNode*>::iterator end){
if(begin == end){
return nullptr;
}
if(distance(begin, end) == 1){
return *begin;
}
int mid = distance(begin, end)/2;
ListNode* left = mergeK(begin, begin + mid);
ListNode* right = mergeK(begin + mid, end);
return mergeLists(left, right);
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
auto begin = lists.begin();
auto end = lists.end();
return mergeK(begin, end);
}
};
實驗總結
pptr的使用,減少了記憶體的浪費,還是用原來的連結串列節點已分配的記憶體。