博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Leetcode-Merge k Sorted Lists
阅读量:4136 次
发布时间:2019-05-25

本文共 5541 字,大约阅读时间需要 18 分钟。

题目:

五种方法

  1. 蛮力算法,两个合并,得到的结果再和另外一个合并,直到最后。
    复杂度为O(N*K^2)
/*------------------------------------------------------------------*/class Solution1 {public:    ListNode* mergeKLists(vector
& lists) {
//两个两个比较,直到最后合成一个(这个方法超时,AC不了)复杂度O(N*K^2) ListNode* result=NULL; if(lists.size()==0) return result; else if(lists.size()==1) return lists[0]; else { for(int i=0;i
=2) { result=merge2Lists(lists[i],result); } } return result; } }private: ListNode *merge2Lists(ListNode*l1,ListNode*l2 ) { if(l1==NULL) return l2; else if(l2==NULL) return l1; else { ListNode *res=NULL; if(l1->val
val) { res=l1; res->next=merge2Lists(l1->next,l2); } else { res=l2; res->next=merge2Lists(l1,l2->next); } return res; } }};

2.

分治法(两个两个合并,第一次合并结束,是k/2个序列,再两个两个合并,第二次合并结束是 k/4,最后的复杂度是O(N*log(K)))

/*------------------------------------------------------------------*/class Solution2 {
//复杂度:O(N*log(K)) 空间复杂度大public: ListNode* mergeKLists(vector
& lists) {
//分治法,一半一半比较,直到最后合成一个(这个方法AC了,不会存在空间超出限制,70%排名) ListNode* result=NULL; if(lists.size()==0) return result; else if(lists.size()==1) return lists[0]; return merg(lists,0,lists.size()-1); }private: ListNode *merg(vector
& lists,int left,int right) { if(left
val
val) { res=l1; res->next=merge2Lists(l1->next,l2); } else { res=l2; res->next=merge2Lists(l1,l2->next); } return res; } }};

3

分治法,不采用递归,复杂度同2,但空间复杂度降低了为O(1)

/*------------------------------------------------------------------*/ //分治法,不采用递归,把第二种递归方法转化为非递归方法class Solution3 {
//复杂度:O(N*log(K)) 空间复杂度小public: ListNode* mergeKLists(vector
& lists) {
//分治法,AC,89%) ListNode* result=NULL; if(lists.size()==0) return result; else if(lists.size()==1) return lists[0]; else { int len=lists.size(); while(true) { for(int i=0;i<=len/2;i++) { if(len%2==0&&i
val
val) { res=l1; res->next=merge2Lists(l1->next,l2); } else { res=l2; res->next=merge2Lists(l1,l2->next); } return res; } }};

4

使用STL的优先队列,即小顶堆的性质。复杂度:O(NK*log(K)) 堆排序

/*------------------------------------------------------------------*///优先队列(其实就是大顶堆排序),使用STL的自动建堆class Solution4 {
//复杂度:O(NK*log(K)) 堆排序public: struct cmp{ bool operator()(ListNode *a,ListNode *b){
//大的在下,小的在上 return a->val>b->val; } }; ListNode* mergeKLists(vector
& lists) { ListNode* result=NULL; if(lists.size()==0) return result; else if(lists.size()==1) return lists[0]; priority_queue
,cmp> queue; for(int i=0;i
next=temp;//以后的元素都赋给prev->next prev=prev->next;//prev指向它的下一个元素 } if(temp->next!=NULL)//也就是说temp所在的链表还有元素(temp后面的),就把temp后面的元素加入堆中 { queue.push(temp->next); } } return head;//返回指向第一个元素的指针,也就是返回已经排好序的一大串 }};

5

自己写的小顶堆,不适用STL的。复杂度同4.

/*------------------------------------------------------------------*///自己建立堆class Solution { public:    ListNode* mergeKLists(vector
& lists){ ListNode* result=NULL; if(lists.size()==0) return result; else if(lists.size()==1) return lists[0]; vector
heap; for(int i=0;i
next=temp; prev=prev->next; } if(temp->next!=NULL) { heap_push(heap,temp->next);//加入新元素,自己写这个函数 } } return head; }private: void makeheap(vector
&heap) { for(int i=heap.size()/2;i>0;i--)//堆的序号是从1到heap.size()/2 minHeap(heap,i); }void minHeap(vector
&heap,int i)//以i为父节点的子树,建立堆{ int lchild=2*i;//i的左孩子节点序号(序号是从1开始) int rchild=2*i+1;//i的右孩子节点序号 int least=i;//临时变量 if(lchild<=heap.size()&&heap[lchild-1]->val
val) { least=lchild; } if(rchild<=heap.size()&&heap[rchild-1]->val
val) { least=rchild; } //上述两个if是为了获取i节点,i节点的左右孩子三个中最小的那个,下标存到least if(least!=i)//不是父节点i { swap(heap[i-1],heap[least-1]); minHeap(heap,least);//避免调整之后以least为父节点的子树不是堆(因为此时左右子树的一个和父节点换了,那么换后的左右子树那个还要继续调整) }}void swap(ListNode *&a,ListNode *&b)//指针作为形参传递,加引用才能在调用时更改其值!(这儿困惑了好久,一直不明白){ ListNode * c; c=a; a=b; b=c;}void heap_push(vector
&heap,ListNode * p){ heap.push_back(p);//把该链表加入heap中 //minHeap(heap, 1); for(int child=heap.size(),parent=child/2;parent>0;child=child/2,parent=child/2) //因为添加的元素是最后一个,所以只需从底部向上进行判断 { if(heap[child-1]->val
val) swap(heap[child-1],heap[parent-1]); }}ListNode*heap_pop(vector
&heap)//删除堆顶的元素,并返回{ swap(heap[0],heap[heap.size()-1]);//把最后一个和第一个交换,是为了方便删除第一个 ListNode* p=heap[heap.size()-1];//获取最后一个 heap.pop_back(); minHeap(heap,1);//重新建立堆(第一步交换后,要重新调整顺序),因为现在的第一个是原来的最后一个,所以要从头到尾堆排序一下 return p;}};

总结:2,3,4,5都AC了,1 TLE。另外自己写小顶堆,错误很多,好多没考虑清楚的,调试了好久,不过写一次确实能锻炼能力。

转载地址:http://kexvi.baihongyu.com/

你可能感兴趣的文章
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
查看>>
Linux Spin lock.
查看>>
Linux, BUG: spinlock recursion on CPU
查看>>
Ubuntu 设置 DNS
查看>>
Ubuntu 设置 dhcpd 不要自动启动
查看>>
Including driver firmware on Linux kernel image
查看>>
can't boot the kernel , if the server side is tftpd32.exe
查看>>
Upstream src code to Android
查看>>
Commit our mod to our own repo server
查看>>
LOCAL_PRELINK_MODULE和prelink-linux-arm.map
查看>>
Simple Guide to use the gdb tool in Android environment
查看>>
Netconsole to capture the log
查看>>
Build GingerBread on 32 bit machine.
查看>>
How to make SD Card world wide writable
查看>>
Detecting Memory Leaks in Kernel
查看>>
Linux initial RAM disk (initrd) overview
查看>>
HOWTO: Booting from SD card using U-Boot
查看>>
HOWTO: Booting from SD card using U-Boot
查看>>
Timestamping Linux kernel printk output in dmesg for fun and profit
查看>>
file lock in the Linux system
查看>>