【Leetcode】 Merge k Sorted Lists

Leetcode第23题:

题目的意思就是讲多个有序的链表合并成一个有序的链表。

 

解题思路:因为所有的链表都是有序的。我们可以将所有链表的首节点拿出来建立一个小根堆。每次取堆顶的节点即最小的节点。取完最小节点后,如果这个最小节点有后续节点,则加到小根堆中,并调整小根堆。再循环上面的操作,取堆顶节点并将下一个节点加到堆中,一直循环直到堆中的元素为空。

 

下面贴出完成代码(这里为了锻炼自己的代码能力,手动实现了一个小根堆。在标准库里面是有个优先级队列的,其实可以直接用)

 

#include <iostream>
#include <vector>

using namespace std;

struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
 };


//小根堆
class ListNodeHeap
{
public:
	ListNodeHeap(size_t cap)
	{
		m_node_array = new ListNode*[cap];
		m_size = 0;
	}
	~ListNodeHeap()
	{
		delete[] m_node_array;
	}

	void Push(ListNode* node)
	{
		if (!node) return;
		m_node_array[m_size] = node;

		int cur_index = m_size;
		while (cur_index > 0)
		{
			int parent_index = (cur_index - 1) / 2;
			if (m_node_array[parent_index]->val <= m_node_array[cur_index]->val)
				break;
			std::swap(m_node_array[parent_index], m_node_array[cur_index]);
			cur_index = parent_index;
		}

		m_size++;
	}

	ListNode* Pop()
	{
		if (Size() == 0)
			return NULL;
		
		m_size--;
		ListNode* ret = m_node_array[0];
		std::swap(m_node_array[0], m_node_array[m_size]);

		int cur_index = 0;
		while (2 * cur_index + 1 < m_size)
		{
			int l_child = 2 * cur_index + 1;
			int r_child = 2 * cur_index + 2;
			int min_index = l_child;
			if (r_child < m_size && m_node_array[r_child]->val < m_node_array[l_child]->val)
				min_index = r_child;

			if (m_node_array[cur_index]->val <= m_node_array[min_index]->val)
				break;
			std::swap(m_node_array[min_index], m_node_array[cur_index]);
			cur_index = min_index;
		}

		return ret;
	}

	size_t Size()
	{
		return m_size;
	}

private:
	size_t m_size;
	ListNode** m_node_array;
};


class Solution {
public:
	ListNode* mergeKLists(vector<ListNode*>& lists) {
		ListNodeHeap node_heap(lists.size());
		ListNode* head = NULL;
		ListNode* cur = NULL;

		for (auto it : lists)
		{
			if (!it) continue;
			node_heap.Push(it);
		}

		while (node_heap.Size() > 0)
		{
			ListNode* tmp = node_heap.Pop();
			if (!tmp)
				break;

			if (!cur)
			{
				cur = tmp;
				head = cur;
			}
			else
			{
				cur->next = tmp;
				cur = tmp;
			}

			if (cur->next)
			{
				node_heap.Push(cur->next);
				cur->next = NULL;
			}
		}

		return head;
	}
};




//下面是测试的相关代码
void PrintList(ListNode* list_node)
{
	while (list_node)
	{
		if (list_node->next)
			std::cout << list_node->val << "->";
		else
			std::cout << list_node->val << std::endl;
		list_node = list_node->next;
	}
}

ListNode* CreateNodeList(int* a, int n)
{
	ListNode* head = NULL;
	ListNode* cur = NULL;
	for (int i = 0; i < n; i++)
	{
		ListNode* node = new ListNode(a[i]);

		if (!cur)
		{
			cur = node;
			head = cur;
		}
		else
		{
			cur->next = node;
			cur = node;
		}
	}
	return head;
}


int main()
{
	Solution s;

	int a1[] = { 1, 4, 5 };
	int a2[] = { 1, 3, 4 };
	int a3[] = { 2, 6 };

	std::vector<ListNode*> vec;
	vec.push_back(CreateNodeList(a1, 3));
	vec.push_back(CreateNodeList(a2, 3));
	vec.push_back(CreateNodeList(a3, 2));

	ListNode* ret = s.mergeKLists(vec);

	PrintList(ret);
}

最终在leetcode上提交给出很好的结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值