Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
思路:将每个链表的头结点取出来,建立一个最小堆,每次取堆顶元素(即K个链表中的最小值),然后将其合并到链表中,再将堆顶元素的下一个元素加入堆中,调整堆,使其满足最小堆,然后再取堆顶元素,如此反复,知道链表中的元素都并入链表中。
说清楚了思路,写程序的重点就在建立堆了,STL中有建堆的方法,这里个人想复习一下建立堆的过程,因此自己写的建堆函数。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//建立最小堆。 i为要调整的节点 heap[i]
void minHeapCreat(vector<ListNode*> &heap, int i)
{
//要调整节点的左孩子节点
int left = 2 * i + 1;
int flag = 0;//
ListNode *temp = heap[i];
while(left < heap.size() && flag != 1)
{
//寻找左右孩子结点中的较小者,如果右孩子节点更小,则选右孩子节点
if(left < heap.size()-1 && heap[left]->val > heap[left + 1]->val)
left++;
//根节点是否小于左右结点,若小于,则停止调整,标志flag置1
if(temp->val < heap[left]->val)
flag = 1;
else
{
/根节点大于左右结点,则a[j]上移
heap[i] = heap[left];
i = left;
left = 2 * i +1;
}
}
heap[i] = temp;
}
void makeHeap(vector<ListNode*>&heap)
{
//从第一个非叶结点开始建堆
for(int i = (heap.size()-2)/2; i >=0 ; i--)
{
minHeapCreat(heap, i);
}
}
ListNode* mergeKLists(vector<ListNode*> &lists)
{
if(lists.empty())
return NULL;
int k = lists.size();//K个链表
vector<ListNode*>heap;
for(int i = 0; i < k; i++)
{
if(lists[i] != NULL)
{
heap.push_back(lists[i]);
}
}
//若每个链表均为空,即lists中有元素,旦每个链表头结点为NULL,则直接返回NULL
//提交的时候 每次都是因为输入类似 [[] []] 要求返回[] 而我的程序返回为空报错。
if(heap.empty())
return NULL;
makeHeap(heap);
ListNode *head = heap[0];//新链表的头结点即为第一次建堆的堆顶元素
ListNode *p = head;
while(!heap.empty())
{
ListNode *minNode = heap[0];
ListNode *pnext = minNode -> next;
if(pnext != NULL)
heap[0] = pnext;
else
{
swap(heap[0],heap[heap.size()-1]);
heap.pop_back();
}
minHeapCreat(heap,0);
p->next = heap[0];
p = p->next;
}
//循环完成之后,p->next置空,
p->next = NULL;
return head;
}
};
运用STL解决的方法后面补上。