23. Merge k Sorted Lists

来源:互联网 发布:淘宝刻假章警察会查吗 编辑:程序博客网 时间:2024/06/14 10:53

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

合并K个已排序的链表,并将排序结果返回,分析和描述复杂性。
 

一看到这道题,由于K个链表已经是排好序的,最简单的做法就是每次找出K个链表里最小的那个元素,放入新的链表中。每次选择一个元素的复杂度是O(k),操作的复杂度是O(n),所以总共的时间复杂度是O(kn),空间复杂度是O(n)

/** * 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) {int n = lists.size();if (n == 0)return NULL;for (int i = 0; i<lists.size(); i++){if (lists[i] == NULL){lists.erase(lists.begin() + i);i--;}}//预处理清楚为空的链表if (lists.size() == 0)return NULL;//特殊情况判断ListNode head(0);ListNode *p = &head;while (lists.size()){int Min = lists[0]->val;int index = 0;for (int i = 0; i < lists.size(); ++i){if (lists[i] != NULL && lists[i]->val < Min){index = i;Min = lists[i]->val;}}//找出K个链表中最小的元素p->next = lists[index];//将找出的元素放到新的链表p = p->next;lists[index] = lists[index]->next;if (lists[index] == NULL)lists.erase(lists.begin() + index);//如果某个链表为空,及时清除}return head.next;}};

上面的做法固然简单,但是复杂度方面仍然有改善的空间。改善的思路就是这周老师上课讲的分治思想,将合并K个链表的任务分成合并更小的链表的任务,比如K/2,又将合并K/2个链表的任务分成合并K/4个链表,一直划分下去直到任务变成合并1个或者2个链表。算法的时间复杂度为O(nklogk),空间复杂度是O(n)。

/** * 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) {        int n = lists.size();        if(n == 0)            return NULL;        while(n > 1)        {            for(int i = 0; i < n/2; ++i)                lists[i] = merge(lists[i], lists[i+(n+1)/2]);//分治归并排序            n = (n+1)/2;        }        return lists[0];    }    ListNode* merge(ListNode* node1, ListNode* node2)    {        ListNode *head = NULL;        if(node1 == NULL)            return node2;//特殊情况判断        if(node2 == NULL)            return node1;//特殊情况判断        if(node1->val <= node2->val)//特殊情况判断        {            head = node1;            node1 = node1->next;        }        else//特殊情况判断        {            head = node2;            node2 = node2->next;        }        ListNode *p = head;        while(node1 && node2)        {            if(node1->val <= node2->val)//找到两个链表最小的元素,放入新的链表            {                p->next = node1;                node1 = node1->next;            }            else            {                p->next = node2;                node2 = node2->next;            }            p = p->next;        }        if(node1)//假如其中一条链表没有到尾巴,剩余的元素全部放入新的链表            p->next = node1;        else if(node2)            p->next = node2;                    return head;    }};




                                             
0 0