力扣23. 合并K个排序链表(分治)

力扣23. 合并K个排序链表(分治)

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

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

示例:

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

 

一、优先法

维护当前每个链表没有被合并的元素的最前面一个,k 个链表就最多有 k 个满足这样条件的元素,每次在这些元素里面选取 val 属性最小的元素合并到答案中。

时间复杂度为 O(k*n*logk)

空间复杂度为 O(1)

ListNode* mergeKLists(vector<ListNode*>& lists)
	{
		ListNode* head = new ListNode(0);
		ListNode* cur = head;
		int nsize = 0;
		//找出非空的链
		for (int i = 0; i < lists.size(); i++)
		{
			if (lists[i] == nullptr)
			{
				nsize++;
			}
		}
		int size = lists.size();
		while (nsize < size)
		{
			//找链的最少值就是链的第一个值的比较
			int temp = 2147483647;
			int num = -1;//记住第几位
			for (int i = 0; i < lists.size(); i++)
			{
				if (lists[i] != nullptr && lists[i]->val <= temp)
				{
					num = i;
					temp = lists[i]->val;
				}
			}
			//找到最小值的行才去合并
			if (num != -1)
			{
				//合并链表
				cur->next = &lists[num][0];
				cur = cur->next;
				cout << cur->val << '\t';
				lists[num] = lists[num]->next;
				//链没有了,空指针,说明完成一条链的合并了
				if (lists[num] == nullptr)nsize++;
			}
		}
		return head->next;
	}

二、分治合并

从归并排序中启发可以用分治合并

ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* merge(vector <ListNode*> &lists, int l, int r) {
        if (l == r) return lists[l];
        if (l > r) return nullptr;
        int mid = (l + r) >> 1;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return merge(lists, 0, lists.size() - 1);
    }

三、汇总

#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;
struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

class Solution
{
public:
	ListNode* mergeKLists(vector<ListNode*>& lists)
	{
		ListNode* head = new ListNode(0);
		ListNode* cur = head;
		int nsize = 0;
		//找出非空的链
		for (int i = 0; i < lists.size(); i++)
		{
			if (lists[i] == nullptr)
			{
				nsize++;
			}
		}
		int size = lists.size();
		while (nsize < size)
		{
			//找链的最少值就是链的第一个值的比较
			int temp = 2147483647;
			int num = -1;//记住第几位
			for (int i = 0; i < lists.size(); i++)
			{
				if (lists[i] != nullptr && lists[i]->val <= temp)
				{
					num = i;
					temp = lists[i]->val;
				}
			}
			//找到最小值的行才去合并
			if (num != -1)
			{
				//合并链表
				cur->next = &lists[num][0];
				cur = cur->next;
				cout << cur->val << '\t';
				lists[num] = lists[num]->next;
				//链没有了,空指针,说明完成一条链的合并了
				if (lists[num] == nullptr)nsize++;
			}
		}
		return head->next;
	}
};

int main()
{
	ListNode head1[3] = { 1,4,5 };
	head1[0].next = &head1[1]; head1[1].next = &head1[2];
	ListNode head2[3] = { 1,3,4 };
	head2[0].next = &head2[1]; head2[1].next = &head2[2];
	ListNode head3[2] = { 2,6 };
	head3[0].next = &head3[1];
	vector<ListNode*> lists;
	lists.push_back(head1); lists.push_back(head2); lists.push_back(head3);
	Solution s;
	auto result = s.mergeKLists(lists);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值