標籤(空格分隔): C++ 算法 LeetCode 鏈表算法
Difficulty: Hardsegmentfault
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.翻譯
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { } };
難度係數:困難code
合併k個有序鏈表並返回合併後的有序鏈表。 分析並說明覆雜度。leetcode
有前面的Merge Two Sorted Lists, 這個題就變得簡單了,k個能夠每次把兩個合併成一個,再把第三個跟剛合併的再合併,依次類推。
時間複雜度$Tn = O(n^2)$, 空間複雜度$O(1)$get
上面的分析方法有點問題,若是老是合併成一個鏈表,會致使此鏈表很長,遍歷時間會加倍,沒有充分利用二分的優點, 因此得兩兩合併效率才高。it
class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists){ if (lists.empty()){ return nullptr; } ListNode *p = lists[0]; // 會超時,必須先兩兩合併才能夠 // while (lists.size() > 1) { // p = mergeTwoLists2(p, lists.back()); // lists.pop_back(); // } while (lists.size() > 1) { auto list1 = lists.back(); lists.pop_back(); auto list2 = lists.back(); lists.pop_back(); p = mergeTwoLists2(list1, list2); lists.insert(lists.begin(), p); } return p; } private: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode *p1 = l1, *p2 = l2; ListNode dummy(-1); dummy.next = p1; ListNode *tempLink = &dummy; while(p1 != nullptr && p2 != nullptr) { if (p1->val < p2->val) { tempLink = p1; p1 = p1->next; } else { tempLink->next = p2; p2 = p2->next; tempLink = tempLink->next; tempLink->next = p1; } } if (p2 != nullptr) { tempLink->next = p2; } return dummy.next; } ListNode* mergeTwoLists2(ListNode* l1, ListNode* l2) { ListNode *p1 = l1, *p2=l2; ListNode dummy(-1); dummy.next = nullptr; ListNode *tempLink = &dummy; while(p1 != nullptr && p2 != nullptr) { if (p1->val < p2->val) { tempLink->next = p1; p1 = p1->next; tempLink = tempLink->next; } else { tempLink->next = p2; p2 = p2->next; tempLink = tempLink->next; } } if (p2 != nullptr) { tempLink->next = p2; } else if ( p1 != nullptr) { tempLink->next = p1; } return dummy.next; } };