LeetCode #23 Merge k Sorted Lists

题目:

https://leetcode.com/problems/merge-k-sorted-lists/description/

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

Difficulty: Hard

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6

即归并多个有序数列。


分析:

首先,想象归并两个有序数列的情形:

指针p1处于数列1的开头,指针p2处于数列2的开头。

要将数列2并入数列1中,则:

①如果p2的值<=p1的值,则移动p2,直到p2为空或p2的值>p1的值;

②否则,即p2的值>p1的值,或p1已到达数列1的结尾,这样就可以确定要把数列2的什么区间插入到数列1的p1处。

区间插入后,p1移动一位,重复以上步骤直到归并完毕。

类似于下图:

归并示意

然后,采用分治法,不断两个两个地归并数列,归并的结果又继续进行两路归并,直到只有一个已排好序的数列。

算法如下:

class Solution {
public:
	ListNode* merge(ListNode* l1, ListNode* l2){	// 归并两个有序数列
		ListNode tmp(0);
        ListNode* result = &tmp;
		result->next = l1;
		ListNode* head = l2;
		
    	if(l1 == NULL && l2 != NULL){
    		return l2;
		}
    	else if(l2 == NULL){
    		return l1;
		}
		
    	ListNode* p1 = result->next;
    	ListNode* p2 = head;
    	ListNode* pre = result;
    	while(p1 != NULL && p2 != NULL){
    		if(p2->val <= p1->val) {
    			ListNode* first = p2;
    			while(p2->next != NULL && p2->next->val <= p1->val){
    				p2 = p2->next;
				}
    			ListNode* last = p2;
    			p2 = p2->next;
    			pre->next = first;
    			last->next = p1;
			}
			pre = p1;
			p1 = p1->next;
		}
		if(p1 == NULL && p2 != NULL){
			pre->next = p2;	
		}
		
		return result->next;
	}
	
    ListNode* mergeKLists(vector<ListNode*>& lists) {	// 归并多个有序数列
        
    	if(lists.size() == 0) return NULL;
    	
    	while(lists.size() > 1){
    		int size = lists.size();
    		int n = size / 2;
    		for(int i = 0; i < n; i++){
    			ListNode* node = merge(lists[2 * i], lists[2 * i + 1]);
    			lists.push_back(node);
			}
			lists.erase(lists.begin(), lists.begin() + 2 * n);
		}
		return lists[0];
    }
};

时间复杂度为 O ( n ⋅ l o g k ) O(n·logk) O(nlogk)。其中n为所有的数字的个数,k为数列的个数。

用时为20ms。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值