鏈表面試題小結

轉自:http://blog.sina.com.cn/s/blog_54b2ce380100uqwr.html

某本書上面說了,鏈表這個東西,實際用的並不多,但是可以提供很好的考察面試者編程技巧和思維能力的素材。這裏總結一下,見過的面試題和對應的候選解法。

題一、 給定單鏈表,檢測是否有環。
    使用兩個指針p1,p2從鏈表頭開始遍歷,p1每次前進一步,p2每次前進兩步。如果p2到達鏈表尾部,說明無環,否則p1、p2必然會在某個時刻相遇(p1==p2),從而檢測到鏈表中有環。

http://ostermiller.org/find_loop_singly_linked_list.html

這篇文章講了很多好的壞得相關算法。

題二、 給定兩個單鏈表(head1, head2),檢測兩個鏈表是否有交點,如果有返回第一個交點。
   如果head1==head2,那麼顯然相交,直接返回head1。
   否則,分別從head1,head2開始遍歷兩個鏈表獲得其長度len1與len2。假設len1>=len2,那麼指針p1由head1開始向後 移動len1-len2步。指針p2=head2,下面p1、p2每次向後前進一步並比較p1p2是否相等,如果相等即返回該結點,否則說明兩個鏈表沒有 交點。

題三、 給定單鏈表(head),如果有環的話請返回從頭結點進入環的第一個節點。
   運用題一,我們可以檢查鏈表中是否有環。
   如果有環,那麼p1p2重合點p必然在環中。從p點斷開環,方法爲:p1=p, p2=p->next, p->next=NULL。此時,原單鏈表可以看作兩條單鏈表,一條從head開始,另一條從p2開始,於是運用題二的方法,我們找到它們的第一個交點即爲所求。

    也可以不斷開環。設重合點爲p3,從p3開始遍歷這個環,同時從表頭開始走,檢查每步是否在那個環中。這個方法大概有nlogn。

   使用快慢指針,第一次相遇,表明存在循環。繼續快慢指針,第二次相遇,得到的iteration步長爲環的長度。分別從相遇點和第一個節點出發,都是步長爲1的指針,當相遇時,得到的iteration步長爲環首的位置。

題四、只給定單鏈表中某個結點p(並非最後一個結點,即p->next!=NULL)指針,刪除該結點。
   辦法很簡單,首先是放p中數據,然後將p->next的數據copy入p中,接下來刪除p->next即可。

題五、只給定單鏈表中某個結點p(非空結點),在p前面插入一個結點。
   辦法與前者類似,首先分配一個結點q,將q插入在p後,接下來將p中的數據copy入q中,然後再將要插入的數據記錄在p中。

題六、給定單鏈表頭結點,刪除鏈表中倒數第k個結點。
   使用兩個節點p1,p2,p1初始化指向頭結點,p2一直指向p1後第k個節點,兩個結點平行向後移動直到p2到達鏈表尾部(NULL),然後根據p1刪除對應結點。
題七、鏈表排序

   鏈表排序最好使用歸併排序算法。堆排序、快速排序這些在數組排序時性能非常好的算法,在鏈表只能“順序訪問”的魔咒下無法施展能力;但是歸併排序卻如魚得水,非但保持了它O(nlogn)的時間複雜度,而且它在數組排序中廣受詬病的空間複雜度在鏈表排序中也從O(n)降到了O(1)。真是好得不得了啊,哈哈。以上程序是遞推法的程序,另外值得一說的是看看那個時間複雜度,是不是有點眼熟?對!這就是分治法的時間複雜度,歸併排序又是divide and conquer。 

double cmp(ListNode *p ,ListNode *q)

{return (p->keyVal - q->keyVal);}

ListNode* mergeSortList(ListNode *head)

{    
    ListNode *p, *q, *tail, *e;   
    int nstep = 1;    
    int nmerges = 0;    
    int i;    
    int psize, qsize;
   
    if (head == NULL || head->next == NULL)        
    {return head;}    
    while (1)        
    {   p = head;    
    tail = NULL;
    nmerges = 0;   
    while (p)        
    {   nmerges++;  q = p;  psize = 0;    
    for (i = 0; i < nstep; i++){        
        psize++;        
        q = q->next;        
        if (q == NULL)break;        
    }    
    qsize = nstep;    
    while (psize >0 || (qsize >0 && q))        
    {        
        if (psize == 0 ){e = q; q = q->next; qsize--;}
       
        elseif (q == NULL || qsize == 0){e = p; p = p->next; psize--;}
       
        elseif (cmp(p,q) <= 0){e = p; p = p->next; psize--;}
       
        else{e = q; q = q->next; qsize--;}
       

發佈了28 篇原創文章 · 獲贊 7 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章