这个算法题目是这样:合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
对于这个算法题目,合并k个升序排序链表,首先可以把问题简化,先想清楚合并2个排序链表是怎么样的。
很明显,合并两个排序链表的方法有两种。
法一:常规思路,指针遍历。
1、首先新建一个头指针head,尾指针tail,两个遍历指针first,sec分别指向要遍历的两个链表。
2、接下来从值最小的节点开始遍历,tail总是停留在遍历的当前位置,tail->next=min(first->val,sec=>val);
3、当first||sec其中为NULL的时候就结束循环,如果另外一个不为NULL,就把tail->next指向不为NULL的链表。
法二:递归思路。
主要就是通过一个指针list1永远指向值最小的那个节点,然后一从层层的打开,直到first/sec为NULL时,return。然后一个一个函数的返回list1,连接起来就是一个有序链表了。
合并k个链表也有两种方法:
1、定义了一个头节点head,head和K个链表一一合并,最后返回head。
2、lists[i]与lists[i-1],两两合并,最后返回lists[i]。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//常规思路代码
struct ListNode* mergeoneLists(struct ListNode* list1,struct ListNode* list2){//合并两个链表
struct ListNode *first = list1;
struct ListNode *sec = list2;
struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *tail = (struct ListNode *)malloc(sizeof(struct ListNode));
if(list1==NULL&&list2!=NULL)
{
return list2;
}else if(list2==NULL&&list1!=NULL)
{
return list1;
}else if(list1==NULL&&list2==NULL){
return NULL;
}
if(first->val < sec->val)//初始化头节点
{
head->next = first;
}else{
head->next = sec;
}
tail = head;
while(first!=NULL&&sec!=NULL)//两个链表都不为空才继续执行
{
if(first->val < sec->val)
{
tail->next = first;
first=first->next;
}else{
tail->next = sec;
sec=sec->next;
}
tail = tail -> next;
}
if(first!=NULL)
{
tail->next = first;
}else if(sec!=NULL)
{
tail->next = sec;
}
return head;
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize){//合并k个链表
int i=0;
struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *pre=NULL;
if(listsSize==0)
{
return NULL;
}
if(listsSize==1)
{
return lists[0];
}
head = mergeoneLists(lists[0],lists[1]);//先合并lists[0]与lists[1]
if(head!=lists[0]&&head!=lists[1])//如果lists[0]与lists[1]都不为空,才往下执行->next
{
head = head->next;
}
if(head==NULL)
{
return NULL;
}
for(i=2;i<listsSize;i++)//将2到listsSize-1的所有链表进行合并
{
pre=head;
head = mergeoneLists(pre,lists[i]);
if(head!=pre&&head!=lists[i])//如果pre与lists[i]都不为空,才往下执行->next
{
head = head->next;
}
}
return head;
}
//递归思路
struct ListNode* mergeoneLists(struct ListNode* list1,struct ListNode* list2){
struct ListNode *change=NULL;
if(list1==NULL)
{
return list2;
}
if(list2==NULL)
{
return list1;
}
if(list1->val>list2->val)//交换list1与list2,保证list1永远指向最小的值
{
change = list1;
list1 = list2;
list2 = change;
}
list1->next = mergeoneLists(list1->next,list2);//递归调用
return list1;
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize){
int i=0;
if(listsSize==0)
{
return NULL;
}
if(listsSize==1)
{
return lists[0];
}
for(i=1;i<listsSize;i++)//合并listsSize个链表
{
if(lists[i-1]==NULL)
{
continue;
}
lists[i]=mergeoneLists(lists[i-1],lists[i]);//合并lists[i-1]与lists[i],并且返回给lists[i]
}
return lists[i-1];
}