Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
这个题的思路还是比较清晰的。两个链表都已经排好序,首先,选择两个链表中头结点较小的作为结果的头结点。然后,依次比较当前位置的下一个节点,将较小的加入结果链表即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *head;
if(l1==NULL && l2==NULL)
return NULL;
if(l2==NULL)
return l1;
if(l1==NULL)
return l2;
if(l1->val>l2->val){
head=l2;
l2=l2->next;
}
else{
head=l1;
l1=l1->next;
}
ListNode *tmp=head;
while(l1 && l2){
if(l1->val>l2->val){
tmp->next=l2;
l2=l2->next;
tmp=tmp->next;
}
else{
tmp->next=l1;
l1=l1->next;
tmp=tmp->next;
}
}
if(l1)
tmp->next=l1;
else
tmp->next=l2;
return head;
}
};
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
这个问题就比较复杂了。如果还按上面的方法,找出所有链表当前节点的最小值加入结果链表,时间复杂度过大。这个问题我们采用分治的方法解决。即把k个链表的问题分解处理,直至分为两个链表的合并,这样就转化为上面的方法了。分治的过程类似归并排序的过程,每次将链表的数目分为等量的两份。代码如下:
/**
* 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) {
if(lists.empty())
return NULL;
return helper(lists,0,lists.size()-1);
}
ListNode* helper(vector<ListNode*>& lists, int l, int r){//分治递归
if(l<r){
int m=(l+r)/2;
return merge(helper(lists,l,m),helper(lists,m+1,r));
}
return lists[l];
}
ListNode* merge(ListNode* l1, ListNode* l2){//双链表合并
ListNode *head;
if(l1==NULL && l2==NULL)
return NULL;
if(l2==NULL)
return l1;
if(l1==NULL)
return l2;
if(l1->val>l2->val){
head=l2;
l2=l2->next;
}
else{
head=l1;
l1=l1->next;
}
ListNode *tmp=head;
while(l1 && l2){
if(l1->val>l2->val){
tmp->next=l2;
l2=l2->next;
tmp=tmp->next;
}
else{
tmp->next=l1;
l1=l1->next;
tmp=tmp->next;
}
}
if(l1)
tmp->next=l1;
else
tmp->next=l2;
return head;
}
};
解决这个问题还有一种方法——用堆来解决。取出每个链表的当前节点,并构建最小堆。那么堆顶的节点即为最小值,可以放入结果链表中,然后将该最小值所在链表的下一个节点加入堆中,重新构建最小堆。重复这个过程,直到堆为空。代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
#define LN ListNode*
#define HEAP heap.begin(),heap.end()
#define PB push_back
#define INF 1000000
struct node
{
int val;
LN from;
node(ListNode* n)
{
if ( n==NULL )
{
val=INF;
}
else
{
val=n->val;
}
from=n;
}
bool operator<(const node& other)const
{
return val<other.val;
}
bool operator>(const node& other)const
{
return val>other.val;
}
};
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (lists.empty()) return NULL;
int n= lists.size();
vector<node> heap;
heap.reserve(n);
for( int i=0;i<n;i++)
heap.PB(node(lists[i]));
make_heap(HEAP,greater<node>());
LN head= new ListNode(0);
LN pL = head;
pop_heap(HEAP,greater<node>());
node small=heap.back();
heap.pop_back();
while(small.val!=INF)
{
LN next=small.from->next;
pL->next=small.from;
small.from->next=NULL;
pL=pL->next;
heap.PB(node(next));
push_heap(HEAP,greater<node>());
pop_heap(HEAP,greater<node>());
small=heap.back();
heap.pop_back();
}
LN ret=head->next;
delete head;
return ret; }
};