小米面經


昨天下午去武大參加小米的筆試,一共三道題,做得很差。本以為必然沒戲了,誰知道早上凌晨1點半來了面試的短信通知。招聘人員真的是辛苦了。

今天下午一點半,在武漢珞珈山國際大酒店進行面試,題目記錄如下:

1.兩個已序數組A,B,將兩個數組進行歸並,並將結果存放在數組B中,B足夠大。例如A={1,3,5},B={2,3,5},結果B={1,2,3,4,5,6}

答:這一題比較簡單。關鍵在於從尾向頭進行賦值,否則可能會覆蓋需要的值。代碼如下(未調試過)

void func(int *A,int lenA,int *B,int lenB)
{
    int m=lenA-1;
    int n=lenB-1;
    for(int i=lenA+lenB-1;i>=0;)
    {
        if(m==0)
        {
            break;
        }
        else if(n==0)
        {
            for(;m>=0;m--)
            {
                B[i]=A[m];
                i++;
            }
        }
        else
        {
            if(A[m]>=B[n])
            {
                B[i]=A[m];
                m--;
                i++;
            }
            else
            {
                B[i]=B[n];
                n--;
                i++;
            }
        }
    }
}

 

2.改進昨天筆試中的一道題目:兩個數組I1,I2,二者只有一個公共子序列,求之。

答:一般求最大公共子序列的方法是動態規划,時間復雜度O(mn)(我昨天筆試就是這么做的,結果只得了12分,滿分20)。但是這一題說明了只有一個公共子序列,因此不必那么麻煩,只要找出I2中也屬於I1的元素就行了。

這一題我首先想到的是bitmap,因為查找速度很快O(1),但是空間復雜度較高,面試官讓我想想能不能把空間復雜度降低,我想到了hashtable.

首先將I1里的數全部存入hashtable,然后遍歷I2,只要該數在hashtable中,證明它是公共子序列中的元素,直接打印出來。這樣時間復雜度就是O(n)了。

代碼我就不貼了,比較簡單。建議大家也看看bitmap,在處理大數據的搜索時,很有用。

 

3.為什么Linux分為內核態和用戶進程態?什么時候這二者會進行切換?

答:這題完全不會,只有硬着頭皮答了。在用戶進程調用系統函數時,會進入內核態。其他就不知道了。

后來面試官給我講了講這一題:之所以分開,是因為內核態可以操作更多的硬件資源,而且不用用戶去關心,如果讓用戶自己操作,可能會產生許多錯誤。用戶態切內核態有三種情況:1.系統調用,2.異常,3.外圍設備中斷。感覺這題和底層硬件關系密切。

 

一面結束,緊接着是二面。

二面的問題乍看之下都很難,但是自己思考其實也沒那么難,我是在面試官的提醒下才答出來的。感覺不怎么好。

1.一個數組中有100w個整數,這些整數的范圍時1~99999,要求打印出重復的數字。

答:最先想到的還是bitmap,但是空間復雜度太高。面試官說改進一下,想破頭沒想出來。最后請求面試官能否告知答案,結果十分之巧妙,估計我自己再多想幾個小時也未必想得出。

解法如下:

這100w個數據存在一個數組里,每一個數可以讓他對應一個位,這叫位圖。舉例來說,假設第一個數是59,我就讓他對應59位,第二個數是63,我就讓他對應63位。如果有重復數字,那么也就是說有多個數對應相同的一位。我們在遍歷的時候,對位做一個記號,如果碰到有的位已經被記號過了,那證明之前已經有過這個數了。

具體來說:假設這個數組是A={59,63,46,.....59,.....},第一個數是59,我們就讓A[59]=A[59]-1000000,這樣A[59]就小於0了,這就是標記。當遍歷到第二個59時,我們會再去檢查A[59],發現A[59]已經小於0了,因此前面肯定一應有了一個59,使A[59]減了1000000,當遍歷到A[59]時,我們去找A[A[59]+1000000]。不知道這么解釋清楚沒有。

 

2.在一定精度內求根號n,n>=1。

答:一接到這一題,我蒙了。記得以前好像做過這題,我沒搞出來,好像方法很復雜,一下沒了信心。面試官提示了我一下,可以用二分法,我一下豁然開朗。

其實就是一個二分查找。代碼如下(沒測試過):

float n;
float e;//精度

float func(float beg,float end)
{
    float f = (beg+end)/2;
    float f2 = f*f;
    if(f2-n<=e && f2-n>=-e)
    {
        return f;
    }
    else if(f2-n>e)
    {
        return func(beg,f);
    }
    else
    {
        return func(f,end);
    }
}

 

3.N個木頭和N個石頭,木頭之間質量兩兩不同,石頭也是。但是木頭的質量和石頭的質量一一對應,現在給你一個天平,將木頭和石頭分成質量一一對應。

答:這一題我都沒直接答出來。瞎了。其實很多題目,當你知道答案以后,覺得很簡單。因此理解答案對我們來說並不困難,只是我們沒有一個很好地方法將思路引向答案。這也與平時我們所受到的教育有關,我們從小到大,受到的都是歐幾里得式的教育。即先給出結論,再證明之。我們從來沒有去探究怎么想到這個結論的。更詳細的內容我推薦大家看看一本書,叫做《暗時間》。

回到這一題,相信大家已經有答案了。最笨的方法當然是一一對比,時間復雜度為O(n^2),有沒有更快的呢?首先,比O(n^2)快一個數量級的時間復雜度是O(nlgn),這不正是比較類排序的下限嗎?給了個天平,正好用於比較。因此,我們用時間復雜度為O(nlgn)的排序方式(快排,歸並,堆排等)將兩堆分別排序即可,排序后就一一對應了。

 

至此,面試結束。

總結一下。感覺小米對算法和思路的要求比較高。我投的是路由器軟件研發,居然沒有問我TCP/IP的知識。小米的編程語言大部分是Java,但是面試的時候,也沒涉及過編程語言的問題。互聯網公司對編程語言問題問得一向很少。其實關鍵在思路,有了思路,用什么語言實現並沒很大差。所以完全沒必要去糾結什么學C++還是JAVA。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM