n個有序單鏈表合併
n個長度為m的有序單鏈表進行合併,使合併之後的單鏈表保持有序,求時間複雜度。這是今年阿里巴巴武漢實習生招聘的一道填空題,我參加了並最終獲得offer只可惜由於事先簽了騰訊所以本著誠信的原則,我選擇放棄阿里相對豐厚的實習生薪水。感覺這是一道很開放的題目,也就是一共有n*m個元素,所以該問題時間複雜度的下限為O(n*m)。下面談談我的想法(以從小到大為準)。
1.暴力法
拿到此題,第一想法就是每次挑選最小的,由於有序,故最小元素只可能是所有單鏈表第一個元素中的最小者,一次挑選時間複雜度為O(n),總共要處理n*m次,所以總的時間複雜度為O(n*m*m),空間複雜度為O(1)。
2.最小堆
從n個元素中找最小的,可以嘗試建立含n個元素的最小堆,每次取最小堆中的根節點元素,然後將該節點所在單鏈表中的下一個元素補上,調整堆維持最小堆的性質,此過程時間複雜度為O(log(n)),總共要處理n*m次,所以總的時間複雜度O(n*m*log(n)),此時必須記錄最小堆對應的拓撲結構,故需額外開闢空間,空間複雜度為O(n)。程式碼相簡單,就不貼上了。
3.歸併排序
原問題可以和歸併排序類比,進而可以看作是已經在歸併排序對應的狀態樹上自底向上進行了log(m)次的,得到n個長度為m的有序單鏈表,接著只需繼續歸併排序的過程即可,還需進行log(n),而每次即對應每一層有n.m的元素,時間複雜度為O(n*m*log(n))無需額外空間,故空間複雜度為O(1)。貼段程式碼:
#include<iostream> #include<ctime> using namespace std; struct SNode { int key; SNode *next; }; class SList { private : SNode *head; public: SList(); void insertSort(int); void insertSort(SList &); void merge(SList &); void print(); }; SList::SList() { head=new SNode; head->next=NULL; } void SList::insertSort(int tmpKey) { SNode *p=new SNode; p->key=tmpKey; p->next=NULL; SNode *pre=NULL,*cur=head->next; while(cur!=NULL) { if(cur->key>=tmpKey) break; pre=cur; cur=cur->next; } if(NULL==pre) { p->next=head->next; head->next=p; } else { pre->next=p; p->next=cur; } } void SList::merge(SList &tempSList) { SNode *p,*q,*com; com=head; p=head->next; q=tempSList.head->next; while(p!=NULL&&q!=NULL) { if(p->key<q->key) { com->next=p; p=p->next; } else { com->next=q; q=q->next; } com=com->next; } if(q!=NULL) com->next=q; if(p!=NULL) com->next=p; } void SList::print() { SNode *p=head->next; while(p!=NULL) { cout<<p->key<<" "; p=p->next; } cout<<endl; } int mergeSort(SList tArray[],int tLeft,int tRight) { if(tLeft==tRight) return tLeft; int mid=(tLeft+tRight)>>1; int l=mergeSort(tArray,tLeft,mid); int r=mergeSort(tArray,mid+1,tRight); tArray[l].merge(tArray[r]); return l; } int main() { int n=10,i,j=0; SList *mySList=new SList[n]; while(j<n) { i=0; while(i++<n) { mySList[j].insertSort(rand()%100); } mySList[j].print(); j++; } mergeSort(mySList,0,9); mySList[0].print(); system("pause"); return 0; }
4.雜湊雜湊法
如果元素方便雜湊雜湊,那麼總的時間複雜度可以有效降到O(n*m),不過空間複雜度會達到O(n*m)。此題元素型別沒說,所以感覺這樣不妥,但也是一種可以想象的解題方向。