(1) Merge Two Sorted Lists
入门题,合并两个有序链表,只需用两个指针分别遍历两个链表即可:
class Solution {
public:
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
ListNode begin(0);
ListNode * tmp1=l1;
ListNode * tmp2=l2;
ListNode * curNode=&begin;
while(tmp1 && tmp2)
{
if(tmp1->val<tmp2->val)
{
curNode->next=tmp1;
curNode=curNode->next;
tmp1=tmp1->next;
}
else
{
curNode->next=tmp2;
curNode=curNode->next;
tmp2=tmp2->next;
}
}
if(!tmp1)
curNode->next=tmp2;
if(!tmp2)
curNode->next=tmp1;
return begin.next;
}
};
(2) Merge k Sorted Lists
进阶题,把两个链表扩展到k个链表。定性思维一开始想到每次比较k个值选出最小一个,这样时间复杂度为O(n*k)明显过大。参考了[1]发现主流的方法利用堆heap来选出每次最小的值,因为堆的特点是选最小的值时间复杂度为O(lgk),所以总的时间复杂度降为O(n*lgk)。
class Solution {
class cmp {
public:
bool operator() (const ListNode* l, const ListNode* r) const {
return (l->val > r->val);
}
};
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
vector<ListNode*>::iterator it = lists.begin();
while(it != lists.end()) {
if(*it == NULL) lists.erase(it);
else ++it;
}
if(lists.size() < 1) return NULL;
ListNode ret(0);
ListNode * curNode=&ret;
int n=lists.size();
make_heap(lists.begin(),lists.end(),cmp());
while(n>0)
{
pop_heap(lists.begin(),lists.end(),cmp());
curNode->next=(lists[n-1]);
curNode=curNode->next;
if(lists[n-1]->next)
{
lists[n-1]=lists[n-1]->next;
push_heap(lists.begin(),lists.end(),cmp());
}
else
{
lists.pop_back();
n--;
}
}
return ret.next;
}
};
注意stl中的heap的用法[2]。
(3) Merge Sorted Array
这次是把链表改成数组,又是定性思维的错,一开始想到还是每次选头两个最小的值,但是这样要进行插入操作(需要把插入点后面的数据全部后移),时间复杂度为O(n*n)。网上搜了一遍参考了[3]发现,如果考虑从后往前比较,这样就不会产生需要数据后移的问题了,时间复杂度O(n)。
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
int a=m-1,b=n-1,c=m+n-1;
while(a>=0 && b>=0)
{
if(A[a]>B[b])
A[c--]=A[a--];
else
A[c--]=B[b--];
}
if(b>=0)
while(b>=0)
A[c--]=B[b--];
}
};
参考:
[1] http://blog.csdn.net/feliciafay/article/details/17468061
[2] http://hi.baidu.com/lcplj123/item/1979df9fdb0642c9b72531aa
[3] http://www.cnblogs.com/remlostime/archive/2012/11/16/2772935.html