LEETCODE专题
23. Merge k Sorted Lists
题目要求:
题目意思很简单,就是给定许多条有序链表,然后让我们合并成一条有序链表再返回即可。
下面简要介绍一下2种思路:
第一种就是比较暴力的方法:在所有的链表中取一个最小的数,然后将对应的链表结点指针往后移一位,同时新建一个链表结点;此后重复所有步骤,只是新建的链表结点要和之前的链表结点相连,其实也就是一个next指针的的问题。
当然在这个过程中要注意2点:1.注意结束条件是所有链表都已经走完;2.要判断下链表是否已经走完,才能决定比不比较该链表结点的值。- 这种方法虽然思路简单些,但是实现起来其实非常的繁琐,不仅每次都要比较k - 1次,而且还要注意很多判断条件,以防内存访问错误(比如访问NULL)。而且每一次比较都要扫描k次,假设一共有n个结点的话,就需要扫描n次,时间复杂度就成了O(nk)了。
第二种方法就是归并排序,做过leetcode第21题的话就会发现,21题简直就是为23题量身订制的接口!
将k个链表分成k / 2份,每2个链表进行一次归并,这样就会得到k / 2个新链表。重复上述过程,链表数目会呈现这样的变化规律:k -> k / 2 -> k / 4 -> … -> 1,最后只存在1条链表就可以返回该链表了。其中每一趟都扫描所有链表1次。- 这种方法思路简单,而且最主要的是可以充分利用已有资源。假设一共有n个结点,那时间复杂度就是O(n logk)了。
下面直接上code:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* merge2Lists(ListNode* l1, ListNode* l2) {
int min;
// get the smaller value of the two value
if (l1 == NULL && l2 == NULL) {
return NULL;
} else if (l2 == NULL || (l1 != NULL &&
l1->val < l2->val) ) {
min = l1->val;
l1 = l1->next;
} else {
min = l2->val;
l2 = l2->next;
}
ListNode * newListNode = new ListNode(min);
ListNode * newhead = newListNode;
while (l1 != NULL || l2 != NULL) {
if (l2 == NULL || (l1 != NULL &&
l1->val < l2->val)) {
min = l1->val;
l1 = l1->next;
} else {
min = l2->val;
l2 = l2->next;
}
newListNode->next = new ListNode(min);
newListNode = newListNode->next;
}
return newhead;
}
/* merge 2 lists to produce a list twice as large
* as the former list. Each pass will take
* O(n). Totally, it has logk passes and thus its
* time complexity is O(nlogk).
*/
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.size() == 0) {
return NULL;
}
ListNode * l1, * l2;
while (lists.size() > 1) {
l1 = lists.back();
lists.pop_back();
l2 = lists.back();
lists.pop_back();
lists.insert(lists.begin(), merge2Lists(l1, l2) );
}
return lists[0];
}
};
时间复杂度:O(n logk)