23. 合并K个排序链表

题目描述

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的优先级小?
    //cmp函数若l1的优先级小于l2的优先级,则返回true,反之,返回false。
	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())
        {
                             //C++容器函数:front(),back()
            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本质是一个堆。

  • 头文件是#include<queue>
  • 关于priority_queue中元素的比较
    模板申明带3个参数:priority_queue<Type, Container, Functional>,其中Type 为数据类型,Container为保存数据的容器,Functional 为元素比较方式。Container必须是用数组实现的容器,比如vector,deque等等,但不能用listSTL里面默认用的是vector
    比较方式默认用operator<(元素越小,优先级越小),所以如果把后面2个参数缺省的话,优先队列就是大顶堆(降序),队头元素最大。
    如果要用到小顶堆,则一般要把模板的3个参数都带进去。STL里面定义了一个仿函数greater<>
    基本类型可以用这个仿函数声明小顶堆。如greater<int>。对于自定义类型,则必须重载operator<或者重写仿函数。
class Solution {
public:
	struct cmp//定义一个可调用类型functional,里面定义的有()运算符
	{   //函数的返回值为l1的优先级是否小于l2的优先级?
		//若l1的优先级小于l2,则返回true,反之返回false。
	    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())
        {
            //C++ queue:front(),back(),push(const T& obj),pop()
            //C++ priority_queue:top(),push(const T& obj),pop()
            //C++ stack:top(),push(const T& obj),pop()
            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;
    }
   
};

posted on 2021-05-16 15:39  朴素贝叶斯  阅读(39)  评论(0编辑  收藏  举报

导航