1. 程式人生 > >LeetCode Merge K Sorted Lists 問題和解答程式 C++ priority queue實現方法

LeetCode Merge K Sorted Lists 問題和解答程式 C++ priority queue實現方法

Merge k Sorted Lists

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

其實這個問題真沒有什麼“技巧”;想多了反而不好。不外乎就兩種方法吧:

1. 各列數量頭一個數組成一個數組,然後取其最大者,插入新的陣列。

2. 反覆呼叫兩個數組合並的函式k-1次

下面是第一種方法,用了STL容器priority_queue來實現。當然還有很多其他方法實現。要使用這個容器的技巧就是:增加一個adaptNode相當於一個adaptor,使得可以使用priority_queue,否則因為原來的ListNode沒有< >的操作而無法使用這個容器的。

#include<iostream>
#include<vector>
#include<functional>
#include<queue>

using namespace std;

//Definition for singly-linked list.
struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

//For adding operator < and >; So that we can form priority_queue
struct AdaptNode{
	int val;
	ListNode *cur;
	AdaptNode(ListNode *node):cur(node)
	{
		if(node == NULL)
			val = INT_MAX;
		else
		{
			val = node->val;
		}
	}

	bool operator<(const AdaptNode& an)const  
	{  
		return val<an.val;  
	}  
	bool operator>(const AdaptNode& an)const  
	{  
		return val>an.val;  
	}  
};

class Solution {
public:
	ListNode *mergeKLists(vector<ListNode *> &lists) {

		if (lists.empty()) return NULL;

		priority_queue<AdaptNode, vector<AdaptNode>, greater<AdaptNode> > pq(lists.begin(),lists.end());

		ListNode head(0);
		ListNode *cura, *small;
		cura = &head;
		small = pq.top().cur;
		
		while (pq.top().val != INT_MAX)
		{
			cura->next = small;
			cura=cura->next;
			pq.pop();
			pq.push(AdaptNode(small->next));
			small = pq.top().cur;
		}
		return head.next;
	}
};

int main()
	try
{
	{
		ListNode head(0);
		ListNode fir(1);
		ListNode sec(2);
		ListNode thi(3);
		ListNode fou(4);
		ListNode fiv(5);
		ListNode six(6);
		ListNode sev(7);
		ListNode eig(8);
		ListNode nin(9);
		ListNode ten(10);
		ListNode da(6);
		ListNode db(9);
		ListNode dc(10);
		ListNode de(19);
		ListNode df(100);
		ListNode *pHead1;
		ListNode *pHead2;
		ListNode *pHead3;

		pHead1 = &head;
		pHead2 = &six;
		pHead3 = &da;

		da.next = &db;
		db.next = &dc;
		dc.next = &de;
		de.next = &df;

		head.next = &fir;
		fir.next = &sec;
		sec.next = &thi;
		thi.next = &fou;
		fou.next = &fiv;
		fiv.next = NULL;

		six.next = &sev;
		sev.next = &eig;
		eig.next = &nin;
		nin.next = &ten;
		ten.next = NULL;

		vector<ListNode *>lists;
		lists.push_back(pHead1);
		lists.push_back(pHead2);
		lists.push_back(pHead3);

		ListNode *pn(NULL);
		Solution solu;
		pn = solu.mergeKLists(lists);
		for(; pn!=NULL; )
		{
			cout<<pn->val<<" ";
			pn=pn->next;
		}
		cout<<endl;
		return 0;
	}
}
catch(out_of_range)
{
	cerr<<"range error\n";
}
catch(...)
{
	cerr<<"unknow exception thrown\n";
}


總結:

指標操作真是灰常煩。要格外小心!!!

12.13update 更新方法2程式:

注意:ListNode *head;代表沒有初始化,而ListNode *head = nullptr;代表已經初始化為nullptr空指標了。

ListNode *mergeKLists2(vector<ListNode *> &lists) {
		if(lists.empty()) return nullptr;
		ListNode *head = lists[0];
		for (int i = 1; i < lists.size(); i++)
		{
			head = mergeTwo(head, lists[i]);
		}
		return head;
	}

	ListNode *mergeTwo(ListNode *n1, ListNode *n2)
	{
		if (!n1) return n2;
		if (!n2) return n1;
		ListNode *t = n1;
		if (n1->val > n2->val)
		{
			t = n2->next;
			n2->next = n1;
			n1 = n2;
			n2 = t;
			t = n1;
		}

		while (t->next && n2)
		{
			if (t->next->val > n2->val)
			{
				ListNode *temp = t->next;
				t->next = n2;
				n2 = n2->next;
				t = t->next;
				t->next = temp;
			}
			else t = t->next;
		}
		if (n2) t->next = n2;

		return n1;
	}

到了現在這種題居然變得這麼簡單了,實現第二種方法感覺就像勢如破竹,一下子通過了。

這種經典的合併程式,基本上可以一口氣寫出來了,還可以任意變換。以前是不敢想象。

不過這個跟某些網上的所謂達到盲打有點不一樣。

我覺得這樣的水平不是死背出來的,而是通過做題,然後熟悉基本方法和操作達到的。

2014-1-25

更新個更加簡潔點的程式。時間複雜度應該是O(n1+n2+n3...)n1,n2,n3...是lists.size()中各個連結串列的長度。空間複雜度是O(1)

ListNode *mergeKLists(vector<ListNode *> &lists) 
	{
		if (lists.empty()) return NULL;
		ListNode dummy(0);
		dummy.next = lists[0];

		for (int i = 1; i < lists.size(); i++)
		{
			ListNode *p = &dummy;
			ListNode *t = lists[i];
			while (t && p->next)
			{
				if (t->val < p->next->val)
				{
					ListNode *tmp = t->next;
					t->next = p->next;
					p->next = t;
					p = t;
					t = tmp;
				}
				else p = p->next;
			}
			if (t) p->next = t;
		}
		return dummy.next;
	}