1. 程式人生 > >演算法設計課第二週作業

演算法設計課第二週作業

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

實驗思路

  1. 因為是已經是排好序的陣列,所以沒必要遍歷一遍生成一個新的陣列再進行遞迴排序,這樣不僅浪費記憶體,也浪費時間。
  2. 所以採用分治的思想,把這個vector中的lists分為兩半,再進行排序。
  3. 遞迴步驟2。
  4. 合併並排序。 ## 程式碼展示
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的使用,減少了記憶體的浪費,還是用原來的連結串列節點已分配的記憶體。