23. 合并K个排序链表

纵然是瞬间 提交于 2019-12-03 11:06:26

题目描述:

Merge k sorted linked lists and return it as one sorted list.Analyze and describe its complexity.

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

方法1:

合并两个链表的扩展,两个两个的合并。

代码:

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int n = lists.size();
        if(n == 0)
        	return nullptr;
        if(n == 1)
        	return lists[0];
        ListNode *ret = lists[0];
        for(int i = 1;i<n;i++)
        	ret = mergeTwoLists(ret,lists[i]);
        return ret;
    }

    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {

    	if(l1 == nullptr)
    		return l2;
    	if(l2 == nullptr)
    		return l1;    	
        ListNode *dummy = new ListNode(-1);
        ListNode *p1 = l1;
        ListNode *p2 = l2;
        ListNode *last = dummy;
        while(p1!=nullptr && p2!=nullptr) 
        {
            if(p1->val <= p2->val) 
            {
            	last->next = p1;
                last = p1;
                p1 = p1->next;
            } 
            else 
            {
            	last->next = p2;
            	last = p2;
                p2 = p2->next;
            }
        }
         
        if (p1 != nullptr)
            last->next = p1;
        if (p2 != nullptr)
            last->next = p2;
        ListNode *ret = dummy->next;
        dummy->next = nullptr;
        delete dummy;               
        return ret;
        
    }
};

方法2:

使用最小堆。

class Solution {
public://cmp函数含义:元素l1是否比元素l2的优先级小?
	static bool cmp(ListNode* l1,ListNode* l2)//堆中各元素优先级大小的确定准则
	{
       return l1->val >= l2->val;//因为要建的是最小堆,元素对应的值越小,它的优先级越大
	}                           //元素对应的值越大,它的优先级越小
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int n = lists.size();
        if(n == 0)
        	return nullptr;
        if(n == 1)
        	return lists[0];
        ListNode dummy = ListNode(-1);
        ListNode *last = &dummy;
        vector<ListNode *> vec;
        for(int i=0;i<n;i++)
        {
        	if(lists[i])//要确保堆中要比较的元素非空
        		vec.push_back(lists[i]);
        }
        //make_heap Defined in header <algorithm>
        make_heap(vec.begin(),vec.end(),cmp);//建堆
        while(!vec.empty())
        {

        	ListNode *temp = vec.front();//堆第一个节点first为最小值节点
        	ListNode *next = temp->next;
        	temp->next = nullptr;
            last->next = temp;                       
            last = temp;
            pop_heap(vec.begin(),vec.end(),cmp);//它把vec[0]和vec[vec.size()-1]交换,然后重新将位置[0,vec.size()-2]调整成一个堆
            vec.pop_back();//容器弹出最后一个节点
            if(next!=nullptr)//要确保堆中要比较的元素非空                                 
            {
            	vec.push_back(next);                
                push_heap(vec.begin(),vec.end(),cmp);//[0,vec.size()-2]已经是一个有效堆
            }                                       //在末尾位置vec.size()-1新加入元素后,重新调整成一个堆
        }

        return dummy.next;
    }
   
};

 

解法3:

和上面使用最小堆的思路一样,不过我们这里直接使用C++的优先队列数据结构,priority_queue本质是一个堆。

1. 头文件是#include<queue>
2. 关于priority_queue中元素的比较
模板申明带3个参数:priority_queue<Type, Container, Functional>,其中Type 为数据类型,
Container为保存数据的容器,Functional 为元素比较方式。
Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector。
比较方式默认用operator<,所以如果把后面2个参数缺省的话,优先队列就是大顶堆(降序),队头元素最大。
如果要用到小顶堆,则一般要把模板的3个参数都带进去。STL里面定义了一个仿函数greater<>,
基本类型可以用这个仿函数声明小顶堆。如greater<int>
对于自定义类型,则必须重载operator<或者重写仿函数。

代码:

class Solution {
public:
	struct cmp//定义一个可调用类型functional
	{
	    bool operator()(ListNode* l1,ListNode* l2)//优先队列中各元素优先级大小的确定准则
	    {
	        return l1->val >= l2->val;//因为要建的是最小优先队列,元素对应的值越小,它的优先级越大
	    }                           //元素对应的值越大,它的优先级越小
    };
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int n = lists.size();
        if(n == 0)
        	return nullptr;
        if(n == 1)
        	return lists[0];
        ListNode dummy = ListNode(-1);
        ListNode *last = &dummy;
        priority_queue<ListNode *, vector<ListNode *>,cmp> q;
        for(int i=0;i<n;i++)
        {
        	if(lists[i])
        		q.push(lists[i]);
        }
        while(!q.empty())
        {

        	ListNode *temp = q.top();
        	ListNode *next = temp->next;
        	temp->next = nullptr;
            last->next = temp;                       
            last = temp;
            q.pop();
            if(next!=nullptr)
            	q.push(next);                          
        }

        return dummy.next;
    }
   
};

  

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!