最多連續數的子集及單連結串列和之戀分析及解答

謝工在GitChat發表於2013-07-02

給一個整數陣列, 找到其中包含最多連續數的子集,比如給:15, 7, 12, 6, 14, 13, 9, 11,則返回: 5:[11, 12, 13, 14, 15] 。

最簡單的方法是sort然後scan一遍,但是要 o(nlgn) , 有什麼 O(n) 的方法嗎?

單連結串列和之戀分析:

原題:兩個單連結串列(singly linked list),每一個節點裡面一個0-9的數字,輸入就相當於兩個大數了。然後返回這兩個數的和(一個新list)。這兩個輸入的list長度相等。 要求是:

  1. 不用遞迴;
  2. 要求演算法在最好的情況下,只遍歷兩個list一次 ,最差的情況下兩遍。

分析:遇到一個面試題,#首先,要澄清和理解題意,確保你的理解和麵試官的本意一致。#題中的單連結串列,可不可以原地修改?是從高位到低位,還是低位到高位?如果是從低位到高位,那麼問題很簡單,是不是?只要兩個指標移動(因為是等長的),對應位置相加,同時記錄是否有進位,產生的結果存入新的連結串列中。

如果是從高到低,問題就複雜了,進位是萬惡之源。這時,也許我們會想到reverse兩個單連結串列(其實,這也是一道很好的面試題,如何做?考慮遞迴和遞推兩種演算法),但這樣做,是不是最好最壞情形都得遍歷兩次?好像不合題意。

如果新的連結串列的節點可以存一個或兩個數字,那麼,第一遍,將相應節點的數字相加,存入新的連結串列,並用一個flag標誌整個操作中是否有進位。如果沒有,結了;否則,再掃描一遍新的連結串列,將有兩個數字的進位存到上一個節點。如果新的連結串列是雙的,問題比較簡單;如果新的連結串列還是單的,這一步也會很複雜,比如,10-〉9-〉9-〉12,如何轉成1-〉1-〉0-〉0-〉2,本身也是一個很好的面試題。這時可能需要reverse連結串列再操作。

如果新的連結串列的節點只能存一個數字,那麼能有什麼辦法?

也許你有更好的解決辦法?期待。

面試題單連結串列和之戀精美解答

本期推薦Hawstein (新浪微博@Hawstein)對於面試題求兩個單連結串列的和的精美分析和解答。如果你對我們的面試題有不同的更優的解答,請回復我們。對於耳目一新的深思熟慮的分析和解答,我們將在此推薦。

今天的 Bonus 面試題:一個單連結串列head,和一個指向表中某個節點的指標p,怎麼以最快的速度刪除指標p所指的節點?

題目

兩個單連結串列(singly linked list),每一個節點裡面一個0-9的數字, 輸入就相當於兩個大數了。然後返回這兩個數的和(一個新list)。這兩個輸入的list 長度相等。 要求是:

  1. 不用遞迴。
  2. 要求演算法在最好的情況下,只遍歷兩個list一次, 最差的情況下兩遍。

解答

這是陳利人同學今天發在待字閨中的面試程式設計題目,看了一下解答, 發現要麼需要遍歷連結串列兩次,要麼需要額外的儲存空間,難道就沒有更優的解法了嗎? 想了一下,發現還是有的。

OK,我們把這個問題具體化一下吧:(這裡就不再考慮從低到高存等blabla情況)

兩個單連結串列,每個節點儲存一個0-9的數字,那麼一個單連結串列就表示一個大數。 從高位到低位存,即表頭對應的是這個大數的最高位。兩個連結串列的長度相等, 我們要返回一個新的單連結串列,是這兩個輸入連結串列代表的數的和。我們不能使用遞迴, 不能使用額外的儲存空間,即空間複雜度是O(1)。只遍歷輸入連結串列一次, 輸出連結串列也是單連結串列(沒有前向指標)。

既然只能遍歷兩個輸入連結串列一次,那我們就從高位加起唄。在這種限制條件下, 這是唯一的出路。然後呢?進位咋整?先加高位,再加低位, 低位產生的進位怎麼加到高位去?我們可沒有前向指標哦親。既然沒有前向指標, 我們就讓一個臨時指標指向高位,當低位相加產生進位時,我們就可以操作高位了。 讓我們看看圖示:

輸入連結串列1: 1 2 3  
輸入連結串列2: 1 2 8  
輸出連結串列:  2 4  
兩個指標:    p q  

當指向輸出連結串列當前結點的指標q發現3+8=11,產生進位,指向高位的p就將結點值加1。 注意,兩個0-9的數相加,要麼不進位,要麼進位為1,只有兩種情況。因此, 我們不用考慮進位是其它數,這一點很重要,後面會看到的。

這樣就OK了嗎?當然不是,如果你遇上連續進位,怎麼破?請看下面的情況:

輸入連結串列1: 1 2 3 4 5  
輸入連結串列2: 1 7 6 5 9

顯然,指向高位的指標p總是緊跟著指向當前結點的指標q是不行的, 這樣當遇上連續進位時,比p更高位的位也需要改變。既然p不能緊跟著q, 我們就不讓它們緊挨著,給它們產生點距離。考慮一下,什麼情況下會產生連續進位? 9! 嗯,遇上9的時候。它要連續進位到哪一位?不為9的那一位。因此,指標p 要停留在和不為9的那一位上,看圖示:

輸入連結串列1: 1 2 3 4 5  
輸入連結串列2: 1 7 6 5 9  
輸出連結串列:  2 9 9 9  
兩個指標:  p       q  

這回當q發現,需要進位了,只需要把p所指結點加1,然後把p,q間的結點都置0即可。 為什麼都置0了呢,因為進位只可能是1,9+1=10,留在該位的自然是0了。

分析完畢,這種方法在任何時候都只需要遍歷輸入連結串列一次,空間複雜度O(1)。

參考程式碼實現

本文來自微信:待字閨中,7月1日釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。

相關文章