题解 | #合并k个已排序的链表#
合并k个已排序的链表
https://www.nowcoder.com/practice/65cfde9e5b9b4cf2b6bafa5f3ef33fa6
1.两个有序链表合并的时间复杂度为N,合并K个链表要达到NlogN的时间复杂度,可以用归并的思想
2.归并排序的思想是,将一个大问题切割成小的问题,然后再将小的问题合并,
比如将数组a一分为二成a1,a2,分别对这两部分排序,然后对这两个数组进行归并。
对于a1,a2来说,又可以分别一分为二,a11,a12,a21,a22,一直这样切割,直到里面的元素只剩一个,那么就可以跟相邻的直接排序,这个过程为分解
最后得到的一定是零散的有序数组,比如a11,a12已经排序OK,那么将这两个合并就得到a1的有序排列,这个过程为合并。
3. 合并K个有序链表,就类似归并排序的合并过程
将K个链表首先分为前后两个部分,前k/2个和后k/2个,前后分别合并,一定会得到两个有序链表,再将这两个合并,就可以了
前k/2个又可以按照前面的步骤继续分解,直到相邻的两个链表或者只剩下一个链表,就可以合并了
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param lists ListNode类一维数组
* @param listsLen int lists数组长度
* @return ListNode类
*/
#include <stdio.h>
#include <stdlib.h>
struct ListNode * mergetwolist(struct ListNode *p1, struct ListNode *p2)
{
struct ListNode *new = NULL, *cur = NULL;
new = (struct ListNode*)malloc(sizeof(struct ListNode));
cur = new;
while (p1 && p2) {
if (p1->val <= p2->val)
{
cur->next = p1;
p1 = p1->next;
}
else {
cur->next = p2;
p2 = p2->next;
}
cur = cur->next;
}
if (p1)
{
cur->next = p1;
}
else {
cur->next = p2;
}
cur = new->next;
free(new);
return cur;
}
void merge(struct ListNode **lists, int h, int t)
{
int mid;
struct ListNode *p1 = NULL, *p2 = NULL;
struct ListNode *new = NULL;
if (t >= h)
{
/*当前是相邻的两个链表,则进行合并*/
if ((t - h) == 1)
{
// printf("fffffffff\n");
p1 = lists[h];
p2 = lists[t];
new = mergetwolist(p1, p2);
lists[h] = new;
return;
}
else if (t == h){
return;
}
}
mid = (t + h) / 2;
// printf("%d %d %d\n", t,h,mid);
merge(lists, h, mid);
merge(lists, mid + 1, t);
new = mergetwolist(lists[h], lists[mid+1]);
lists[h] = new;
return;
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsLen ) {
// write code here
struct ListNode *fast = NULL, *slow = NULL;
if(0 == listsLen)
{
return NULL;
}
merge(lists, 0, listsLen-1);
return lists[0];
}

查看1道真题和解析