Merge k Sorted Lists 合并K个排序链表

合并 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

思路:这道题的基本思路是选取k个列表,每次找出列表中最小的元素拼接到新的列表中,这样逐个拼接便可以实现合并后的排序链表。假设所有的节点个数是N,而找出k个列表中最小的元素需要k次比较,所以综合复杂度是:kN。如果采用优先队列,队列的元素是pair<int,ListNode*>,int是列表的指针对应的值,ListNode*是每个列表的指针(相当于队列当前遍历的下标)。由于优先队列的比较次数是log(k),所以时间复杂度降到了nlogk。

参考代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
struct tmp {
	bool operator()(pair<int, ListNode*> a,pair<int, ListNode*> b) {
		return a.first > b.first;
	}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
	ListNode* pre_head = new ListNode(-1);
	ListNode* t = pre_head;
	priority_queue<pair<int, ListNode*>, vector<pair<int, ListNode*>>, tmp> pq;
	for (int i = 0; i < lists.size(); i++) {
		if (lists[i] != nullptr) {
			pq.push({ lists[i] ->val,lists[i] });
		}	
	}
	while (pq.size() > 0) {
		for (int i = pq.size(); i > 0; i--) {
			t->next = new ListNode(pq.top().first);
			ListNode* ttmp = pq.top().second->next;
			pq.pop();
			if (ttmp)
				pq.push({ttmp->val,ttmp});
			t = t->next;
		}
	}
	return pre_head->next;
}
};

思路二:采用分治法,每次merge 2个数组,虽然每次merge的时间复杂度是n,但是merge的总次数降到了logk次,所以时间复杂度也是nlogk。

参考代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
void mergeToListNode(ListNode* &first, ListNode* &second) {
	ListNode* pre_head = new ListNode(-1);
	ListNode* tmp = pre_head;
	while (first && second) {
		tmp->next = new ListNode(first->val < second->val ? first->val : second->val);
		if (first->val < second->val)
			first = first->next;
		else
			second = second->next;
		tmp = tmp->next;
	}
	while (first) {
		tmp->next = new ListNode(first->val);
		tmp = tmp->next;
		first = first->next;
	}
	while (second) {
		tmp->next = new ListNode(second->val);
		tmp = tmp->next;
		second = second->next;
	}
	first = pre_head->next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
    if (lists.size() == 0)
		return nullptr;
	int interval = 1, amount = lists.size();
	while (interval < amount) {
		for (int i = 0; i < (amount - interval); i += interval * 2) {
			mergeToListNode(lists[i], lists[i + interval]);
		}
		interval *= 2;
	}
	return lists[0];
}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值