23-Merge k Sorted Lists

来源:互联网 发布:云计算服务级别sla 编辑:程序博客网 时间:2024/06/06 05:01

难度:hard
分类:divide and conquer

1.题目描述

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

2.算法

刚开始的时候直接尝试像归并排序一样,将排好序的数组两两合并,但是对于指针链表的排序容易出错。所以,最后采用的算法是:
(1)直接将所有排序好的数组放到一个数组中,
(2)使用上一篇博客的归并算法对合并后的数组进行排序,
(3)将排序好的数组重新生成一个链表并返回头节点。

3.代码实现

(leetcode上面只需要提交类,此处代码包含自己的测试)

//  使用归并排序实现 #include <iostream>#include <vector>using namespace std;struct ListNode {    int val;    ListNode *next;    ListNode(int x) : val(x), next(NULL) {}};class Solution {public:    ListNode* mergeKLists(vector<ListNode*>& lists) {        int arr[10000];        int len = lists.size();        int index = 0;        //  all lists into one array         for (int i = 0; i < len; ++i) {            ListNode* node = lists[i];            while (node != NULL) {                arr[index++] = node->val;                node = node->next;             }        }        int n = index;        //  sort the array        mergeSort(arr, 0, n - 1);        //  change array into a single list        ListNode* temp = new ListNode(0);        ListNode* head = temp;        for (int i = 0; i < n; ++i) {            temp->next = new ListNode(arr[i]);            temp = temp->next;        }        return head->next;    }    void mergeSort(int* array, int min, int max) {        //  注意结束条件的判断         if (min >= max) return;        int mid = (min + max)/2;        //  递归,时间复杂度为O(nlogn)         mergeSort(array, min, mid);        mergeSort(array, mid + 1, max);        combineSub(array, min, mid, max);    }    int temp[10000];    void combineSub(int* array, int min, int mid, int max) {        //  因为两个子数组已经是排序了的,所以只需要不断地比较第一个数,        //  然后往后移动直到将所有的数字放到一个总的数组里面即可         int i = min, j = mid + 1, index = min;        while (i <= mid && j <= max) {            if (array[i] < array[j]) {                temp[index++] = array[i++];            } else if (array[i] > array[j]) {                temp[index++] = array[j++];            } else {                temp[index++] = array[i++];                temp[index++] = array[j++];            }        }        while (i <= mid) {            temp[index++] = array[i++];        }        while (j <= max) {            temp[index++] = array[j++];        }        for (int i = min; i <= max; ++i) {            array[i] = temp[i];        }    }};int main() {    Solution solution;    vector<ListNode*> lists;    int m, n, value;    ListNode* head1 = NULL, *head2 = NULL;    ListNode* temp1 = NULL, *temp2 = NULL;    head1 = temp1;    head2 = temp2;    cin >> m >> n;    for (int i = 0; i < m; ++i) {        cin >> value;        if (i == 0) {            temp1 = new ListNode(value);            head1 = temp1;        } else {            temp1->next = new ListNode(value);            temp1 = temp1->next;        }        if (i == 1) {            head1->next = temp1;        }    }    for (int i = 0; i < n; ++i) {        cin >> value;        if (i == 0) {            temp2 = new ListNode(value);             head2 = temp2;        } else {            temp2->next = new ListNode(value);            temp2 = temp2->next;        }        if (i == 1) {            head2->next = temp2;        }    }     lists.push_back(head1);    lists.push_back(head2);    ListNode* head = solution.mergeKLists(lists);    while (head != NULL) {        cout << head->val << " ";        head = head->next;    }    cout << endl;    return 0;}

4.小结

在实现的过程中,要特别注意指针部分,容易出错。再将数组中的数字转换为链表的时候,因为temp不断地往后移动,所以需要将头节点保存,但是注意不能仅仅复制head=temp,还需要保证head->next = temp->next

//  change array into a single listListNode* temp = new ListNode(0);ListNode* head = temp;for (int i = 0; i < n; ++i) {    temp->next = new ListNode(arr[i]);    temp = temp->next;}return head->next;

5.时间复杂度

在将链表转换为数组和将数组转换为链表的两个过程中,时间都是O(n),而对数组进行排序的时候,采用的是归并排序,时间复杂度是O(nlogn),所以总的时间复杂度是O(nlogn).

原创粉丝点击