1. 程式人生 > >面試經歷之阿裏雲

面試經歷之阿裏雲

怎麽辦 是把 樹的直徑 算法 為什麽 題目 需要 開始 隨機

阿裏雲彈性計算團隊春招實習內推面試+阿裏雲盤古團隊秋招內推面試。

(實習內推面試掛在二面,秋招內推面試已經面完四輪)

首先是學長幫忙內推了他們組的春招實習,過程十分坎坷。18年春節前阿裏雲的一個SDN團隊招實習生,我報名了,接受了內推,在第一次面試後就掛掉(不太明白為啥),但是由於每個人一個批次只能內推一次,所以內推學長組的時候,找了很久的客服,最後由於我的拒絕理由是轉部門,所以可以第二次內推,總之十分艱辛。

實習內推一面(電話面試,大約1小時20分鐘):

1. 自我介紹

2. 對著簡歷問,先問了幾個STL的實現,具體記不太清楚了,後面問了幾個TCP的問題,都比較簡單。

3. 問到項目,首先是第一個項目讓我講了整體的架構,裏面涉及到本地數據庫的存儲結構,問了一下表的結構怎麽設計的,由於表項比較多,之後我提出了一個在本地文件存儲,然後在數據庫中存文件路徑的方案,然後問了我如何保證數據一致性的問題,我用了個隊列來搞,其實就是個數據庫事務的問題(現在想想那時候自己真的是菜)。之後由於我的項目是使用Reactor模型來編程的,所以又問了我關於服務器模型和多路復用的東西,這些能說的就比較多,大概講了30分鐘的epoll、poll、select區別和原理,還有高性能服務器模型(詳見之前我的博客)。

4. 算法題,多路歸並,比較經典的問題了,但是我是第一次碰到,想了一會想出了nlgn的解法,大概說了一下,然後讓我寫代碼實現一個堆,很遺憾的是那時候我完全忘了堆怎麽寫,想了很久也沒想起來(尷尬),然後就讓我寫了一個快排,幸好這個還比較熟悉,順利完成。

總體感覺自己表現一般,堆排序那裏沒想起來太不應該了,而且對數據庫的了解一直是弱項。

實習內推二面(視頻面試,大約1小時):

1. 這次面試,只有一道題,一道很簡單的算法題,給你一棵樹,然後給你一個序列,問這個序列是不是樹的某一枝,非常簡單,一個dfs加上點處理就可以,唯一比較坑的地方就是給定函數原型,但是我自己犯二沒寫一個return true,後期一直在debug也沒發現,等發現了問題也晚了。

掛在了二面,自己犯傻了,沒啥說的,有點可惜。

阿裏實習面試掛掉,自己還是太弱了。

秋招提前批的內推,學長說他們組已經有倆實習生了,那邊可能不好進,我就找了在盤古團隊的學姐幫忙內推,然後之前學習了一下mapreduce,gfs和bigtable的三篇論文,算是對分布式存儲有了一定的了解。

秋招內推一面(電話面試,大約1小時10分鐘):

1. 自我介紹

2. 你對分布式存儲有了解嗎,我說了一下自己學習過三篇論文,然後問我了解paxos算法不,一面的時候還沒看完bigtable,所以不太了解,就說自己不太會,然後問了我hdfs如果節點出故障了怎麽辦,我回答了master故障和chunk故障時的幾種措施,順便把整個hdfs的工作流程和數據一致性的問題也講了一遍,大概耗費了20多分鐘。

3. 我看你簡歷上寫在頭條實習做了jpeg圖片方面的一些東西,能大概說一下嗎,接著就粗略講了一下jpeg算法的步驟和原理,又花了20分鐘。

4. 第一道算法題,多路歸並(怎麽阿裏雲這麽喜歡問多路歸並),問題不大,歸並思路,維護一個堆就行,復雜度nlgn,開始時候寫了個nlgnlgn,後來優化了一下。

5. 第二個算法題,不需要敲代碼,只說思路,求二叉樹的直徑,經典問題,兩次dfs,又問我了證明,大二時候證明過,但是忘了,想了兩分鐘沒想起來怎麽做的,面試官就說那就不用了,面試結束之後想起來咋證明的了,尷尬。

6. 你有沒有什麽問題問我的?我詢問了一下這個組是做一些什麽的,說是分布式存儲的塊存儲,然後又問了一下有沒有對我以後的學習的建議,他說沒什麽建議。

一面自己評價還不錯,問的問題都準備過或者接觸過,也比較熟悉,所有問題都有話可說。

秋招內推二面(視頻面試,大約2小時30分鐘)

1. 自我介紹

2. 開始和我聊在頭條的工作,和jpeg算法有關的東西,這一部分簡直是刷新了我對面試的認知,對每一個細節都死摳到底,比如我提到我的cuda的jpeg縮略程序效率是go自帶庫的10倍,就問了我這個效率是怎麽定義的,考慮到go的庫用到了cpu的幾個核心了嗎,再比如我說官方說NPP庫的效率優化50倍以上,而我的只優化了10倍,為什麽會有這種差距,可能有什麽原因,再比如jpeg格式可以這樣處理,那其他格式的圖片如何處理,如何優化,如果用你說的雙線性插值算法,對其他格式而言需要解決什麽問題,整個這個階段就在一直問我和圖片有關的每一個細節問題,不過幸好的是我對於圖片的調研和了解還比較全面和細致,基本上所有他問到的點都有過研究,所以都答的還不錯,最後問了一下我對於整個實習階段有什麽收獲,我的回答是這次實習讓我覺得自己更有自信能勝任一個從沒有接觸過的領域,第一次接觸圖片領域,通過自學和研究能完成任務,讓我覺得無論以後在哪個方向上工作,都能很快速地入門,其次收獲就是拓寬了自己的知識面。這個階段一共用了1小時20分鐘。

3. 一些基礎問題,了解STL源碼的內部實現嗎,說幾個,deque和list的內部實現是怎麽樣實現的?deque我只用過,沒看過源碼,這個沒答上。然後問了C++面向對象的問題,我說了自己對面向對象了解不多,然後簡單講了一下面向對象的封裝、繼承和多態。最後問了下TCP的慢啟動,比較簡單,把慢啟動、擁塞避免、快速恢復和快速重傳都說了一遍。

4. 一道算法題,如何不用遞歸寫歸並排序(咋又是歸並啊),開始我給的答案是用棧來模擬遞歸,向棧裏壓入區間,然後利用遞歸的思想去做,這種做法是可以的,但是他不讓我用棧,然後我想的是把無序隊列分解成若幹個有序隊列進行多路歸並,但是對於類似於5,4,3,2,1這種倒序數組這個算法的復雜度就會退化到n2。最後我想出了辦法,用一個變量記錄跨度,初始化為1,每歸並一次都*2,一直到這個跨度大於了數組長度,每一趟都能保證一個跨度內的數組是有序的,這樣相當於一個二叉樹的合並的過程,需要註意點的地方就是邊界的問題,整體代碼不難寫,就是細節的地方很多,我倆一起debug了一會,把邊界問題處理好了。期間又個小問題就是我習慣開數組的時候開max值+10,被小小批評了一下,說你們搞競賽的有些習慣不太好。

5. 閑聊時間,他給我講了一些關於分布式存儲的東西,比如什麽樣的需求需要設計什麽樣的分布式系統等等,最後我按照自己的慣例問了他根據我的面試對我有什麽建議,回答是,基礎知識比較紮實,自學能力和溝通能力都比較強,就是建議有兩點,第一,無論以後讀研還是工作,都最好深入一個領域去研究,第二就是改掉一些不良的編程習慣。

本次面試堪稱膀胱面試,說了150分鐘,簡直口幹舌燥,不過自我感覺挺不錯的,這個面試官也算是我之前的所有面試中問問題最有水平最細致的面試官了,對他印象挺不錯的。

秋招內推三面(電話面試,大約40分鐘):

1. 藍橋杯是什麽東西?(這個問題有點尷尬哈)

2. 能說一下你在你們隊伍的三個人中是主要負責什麽的嗎,你們比賽的時候怎麽配合的?此處吹了一波尚神,不過由於尚神還在盤古實習,就沒提他的名字,只說了某隊友。

3. 算法題,正則表達式的匹配,經典dp問題,開始給了一個指數級的搜索算法,後來說了dp,但是我的dp功力還是不太行,有幾個細節問題沒說好。

4. topk問題,給你一個文件,裏面每一行都有一個在一定範圍內的自然數,文件很大,比內存要大,如何求前百分之一的數字的最小值,也就是第百分之一大的值。開始給了多路歸並的想法,分割文件後每個文件取前百分之一,然後reduce,但是這個有瑕疵,就是可以構造不符合的數據,然後我提出了再隨機化一下。接下來的想法是把文件切分之後分別讀取,並且維護一個大小為0.01*n大小的堆進行處理,然後問題是如果0.01*n也比內存大怎麽辦,最後他提醒了我一下,前面有個條件,數字有範圍,恍然大悟,直接桶排序就好了。簡直無地自容啊,經驗主義害死人,一直考慮topk了。接下來問題是如果數字沒有範圍,然後文件大小比內存小,怎麽做,標準topk問題,兩個方案,第一個用堆,第二個類似於快排的那種。

5. 操作系統中不同的進程為什麽不能互相訪問地址,而線程可以,因為是虛擬地址,進程內得到的地址並不是真正的物理地址,而線程有獨立的棧空間但共享堆空間。

6. 共享內存是如何實現的?這個答的不好,我答了shmat族的幾個函數的我的自己的理解,也不知道對不對。

7. 說一下I/O多路復用是如何實現能同時監聽多個文件描述符的,這個就又把select、poll和epoll的原理和對比講了一遍。

三面自我感覺是涼了,幾個點沒答好:dp的細節沒考慮好,topk犯了經驗主義錯誤,忽略了一個條件,感覺自己已經和阿裏雲say goodbye了。

秋招內推四面(視頻面試,大約1小時):

1. 聊了聊工作的東西,對於jpeg的一些東西,這個不說了,基本他問的二面都問過了。

2. 對於你工作裏用的gpu,你是怎麽理解的,你覺得還能完成什麽任務,我說了一些gpu的基本構成和優點,然後說了在機器學習上可能會用到,然後他讓我說了一下我對機器學習的了解,就大概說了一些比較淺顯的東西。

3. C++虛函數的一些東西,我這個面向對象是真的不太行,就說了點多態的東西就沒啥說的了。

4. TCP和UDP的區別,然後舉個實際的例子說一下應用場景,先說了區別,比較簡單,應用的話TCP在傳輸文件的時候可以,UDP在視頻、音頻通話的時候應用比較多。

5. 算法題,對於一個二維鏈表,每個節點有兩個指針:next和child,如何能把它展開成一個一維鏈表,順序隨意,讓child都是null,所有節點利用next連接。其實二維鏈表說白了就是個二叉樹,next就是lchild,child就是rchild,我們的目的是把二叉樹變成一個單鏈,所有rchild都是null。開始給的是直接dfs得出dfs順序,然後直接創建一個鏈表,但是不能額外開空間,想了一會之後想到了,在dfs的過程中判斷一下每個節點的左右孩子是否為空,分情況處理,用一個額外指針維護當前的最尾部的那個節點就可以了,具體代碼如下:

//評測題目: 二維鏈表
struct Node {
    int val;
    Node *next;
    Node *child;
};

Node *last = null;

void dfs(Node *head, Node *father) {
    if(head -> next == null && head -> child == null) {
        if(father -> child != null) {
            head -> next = father -> child;
            father -> child = null;
            dfs(head -> next, head);
        } else {
            last = head;
            return;
        }
    } else if(head -> next == null && head -> child != null) {
        head -> next = head -> child;
        head -> child = null;
        dfs(head -> next, head);
    } else if(head -> next != null && head -> child == null) {
        dfs(head -> next, head);
    } else {
        dfs(head -> next, head);
        last -> next = head -> child;
        head -> child = null;
        dfs(last -> next, last);
    }
}

本來以為三面就涼涼了,結果還是來了四面,挺驚喜的,整個過程也算比較順利。

面試經歷之阿裏雲