1. 程式人生 > >與 30 家公司過招,得到了這章面試心法

與 30 家公司過招,得到了這章面試心法

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

筆者座標上海,做技術開發,之前有幾個月的時間,基本上都是在面試中度過的。我求職的職位是 Linux 伺服器開發,最傾向的職位是伺服器開發主程或技術經理。在那幾個月的求職過程中,我面試了 30+ 家公司,包括騰訊、百度、阿里的螞蟻金服和國際支付寶部門、餓了麼、愛奇藝、360、攜程網、京東、華為、bilibili 與 UCLOUD 等。在這個過程中,思考了一些面試相關的問題,總結出這篇文章,希望給讀者一些啟發。

總結下來,技術面試大致有三種情形,下邊一一來講講。

一、考察資料結構和演算法為主

IT 公司一般都會考察資料結構和演算法能力,其中以百度與愛奇藝等為代表,面試官一般是先簡單地瞭解你之前的工作經歷和專案經驗,然後就直接出演算法和資料結構的題目,具體涉及到以下內容:

  • 快速排序。考察的地方包括演算法步驟、平均演算法複雜度、最好和最壞的情形,有人說校招要把演算法寫出來,我這裡是社招,所以一般描述一下演算法過程即可。
  • 二分查詢法。一般面試官會要求面試者把演算法寫出來,或者先結合一個具體場景來提問,需要你聯想到要使用該演算法,比如求一個數的平方根,接著要你把它具體實現。
  • 連結串列
    。常見的面試題有要求你寫出從一個連結串列中刪除一個節點的演算法、單鏈表倒轉、兩個連結串列找相交的部分等,一般需要完全無誤地寫出來。
  • 實現一些基礎的函式。例如 strcpy、memcpy、memmov 與 atoi 這些函式,面試官會要求你用自己的理解和思路去實現。同樣,這些一般也需要完全無誤地寫出來,並且要保證高效,比如你的實現中有動態分配堆記憶體,那麼這道題目就算答錯。

連結串列和實現基礎函式的關鍵點一般在於考察你的程式碼風格、對邊界條件的處理,比如判斷指標是否為空,千萬不要故意不考慮這種情形,即使你知道也不行,只要你不寫,一般面試官就認為你的思路不周詳,容錯率低;再比如,單鏈表的倒轉,最後的返回值肯定是倒轉後的連結串列頭結點,這樣才能引用一個連結串列,這些都是面試官想考慮的重點。

  • 雜湊表。對雜湊表的細節要求很高,比如雜湊表的衝突檢測、雜湊函式常用實現、演算法複雜度;比如百度二面就讓我寫一個雜湊表插入元素演算法,元素型別是任意型別。
  • AVL 樹與 B 樹。考察概念與細節,比如會問 MySQL 資料庫索引的實現原理,基本上就等於在問你 B 樹。 
  • 紅黑樹。這個基本上是必問的資料結構,包括紅黑樹的概念、平均演算法複雜度、最好最壞情況下的演算法複雜度、左右旋轉與顏色變換。面試官常見的套路有:你熟悉 C++ 的 stl 嗎?你說熟悉,ok,stl 的 map 用過吧?用過,ok,那 map 是如何實現的?紅黑樹,ok,那什麼是紅黑樹?這樣提問,紅黑樹就開始了。Java 的也類似。

二、考察作業系統原理等基礎技術

這一種以餓了麼、bilibli、喜馬拉雅、360 與攜程等為代表,主要兼顧演算法與資料結構,但重點放在其它開發技術,比如作業系統原理、網路協議細節與具體的開發庫原始碼等內容。

基礎的 C++ 問題

以 C++ 語言為例,這一類常見的問題有:

  • C++ 的繼承體系中 virtual 關鍵字的作用,如繼承關係中解構函式為什麼要申明成 virtual 函式,如果不申明為 virtual 會有什麼影響、再涉及到父子類時構造與解構函式的執行順序、多重繼承時類的成員列表在地址空間的排列;
  • static 關鍵字的作用,static_cast、reinterpret_cast 與 dynamic_cast 等幾個轉換符的使用場景;
  • 問得最多的就是虛表的佈局,尤其是菱形繼承,即 B 和 C 繼承 A,D 繼承 B 和 C,每個物件的空間結構分佈,比如問 D 有幾份虛表,D 中 B 和 C 的成員空間排布。

另外,如果你應聘的職位使用 C++ 開發,很多公司會問你一些 C++ 11 的東西,或者問 boost 庫,基本上都一樣。這個你用過就用過,沒有用過就說沒用過不要裝 X,常見的 C++ 11 需要掌握的一些技術庫我也列舉一下吧:

  • auto 關鍵字
  • for-each 迴圈
  • 右值及移動建構函式
  • std::forward、std::move
  • stl 容器新增的 emplace_back() 方法、std::thread 庫、std::chrono 庫
  • 智慧指標系列 std::shared_ptr、std::unique_ptr、std::weak_ptr,智慧指標的實現原理一定要知道,最好是自己實現過
  • 執行緒庫 std::thread
  • 執行緒同步技術庫 std::mutex、std::condition_variable、std::lock_guard 等
  • lamda 表示式(Java 中現在也常常考察 lamda 表示式的作用)
  • std::bind、std::function 庫

網路通訊問題

考察對網路協議的理解和掌握程式,比如 TCP/IP 協議棧的層級關係,三次握手和四次揮手的細節,注意我說的是細節,比如 CLOSE_WAIT 和 TIME_WAIT 狀態。bilibili 問了這樣一個問題,你可以感受一下:

A 與 B 建立了正常連線後,從未相互發過資料,這個時候 B 突然機器重啟,問 A 此時處於 TCP 什麼狀態?如何消除伺服器程式中的這個狀態?

再羅列其它一些常見問題:

  • 萬得問過流量擁塞和控制機制
  • 騰訊問過 TCP 和 IP 包頭常見欄位有哪些
  • 東方財富網問了阻塞和非阻塞 socket 在 send、recv 函式上的行為表現
  • 非同步 connect 函式的寫法
  • select 函式的用法
  • epoll 與 select 的區別,基本上只要問到 epoll,必問 epoll 的水平模式和邊緣模式的區別
  • 一些 socket 選項的用法,nagle、keepalive、linger 等選項的區別
  • TCP 與 UDP 的區別和適用場景
  • 通訊協議如何設計避免粘包
  • HTTP 協議的 get 和 post 方法的區別,問得比較深的會讓你畫出 HTTP 協議的格式
  • 可能會問到 Windows 完成埠模型(IOCP)

總之,網路通訊問題能搞得多清楚就搞多清楚,最起碼把 TCP 應用層各種 socket API 的用法細節搞清楚。

作業系統原理

上海黃金交易所和喜馬拉雅聽書都問了 Linux 下 elf 檔案的節結構,對映到程序地址空間後,分別對應哪些段。相關的問題還有全域性變數、靜態儲存在程序地址空間的哪裡。餓了麼二面問了作業系統的保護模式真實模式、中斷向量表、Linux 下的 CAS。Linux 系統下可能還會問什麼是 daemon 程序,如何產生 daemo 程序,什麼是殭屍程序,殭屍程序如何產生和消除。

堆和棧的區別,棧的結構、棧的細節一點要搞得特別清楚,因為一些對技術要求比較高的公司會問得比較深入,例如京東的一面是讓我先寫一個從 1 加到 100 的求和函式,然後讓我寫出這個函式的彙編程式碼,Java 開發的同學可能會讓你試著去寫一點 JVM 的指令。如果你對棧的結構,如函式引數入棧順序、函式區域性變數在棧中的佈局、棧幀指標和棧頂指標位置不熟悉的話,這題目就無法答對了。

棧的問題,可能會以常見的函式呼叫方式來提問,常見的有 __cdecl、__stdcall、__thiscall、__fastcall 的區別,比如像 printf 這樣具有不定引數的函式為什麼不能使用 __stdcall。

此外還有程序和執行緒的聯絡與區別,問得最多的就是執行緒之間的一些同步技術,如互斥體、訊號量、條件變數等,Windows 上還有事件、臨界區等,這類問題還可以引申為什麼是死鎖、如何避免死鎖。這些東西你必須熟悉到具體的 API 函式使用的層面上來。這是實際開發工作中編碼最常用的東西,如果你連這個都不能熟練使用,那麼你多半不是一個合格的開發者。

程序之間通訊的常用技術也需要掌握,Linux 常用的通訊方式有共享記憶體、匿名和具名管道、socket、訊息佇列等等,管道和 socket 是兩個必須深入掌握的考察點。

使用過的開源技術

考察使用過的開源技術,比如 Redis 與 MySQL 等專案。開源技術的使用一般不做硬性要求,但是這裡必須強調一下 Redis,熟練使用 Redis 甚至研究過 Redis 原始碼,現在一般是對做後臺開發的技術硬性要求。

基於 Redis 的面試題既可以聊演算法與資料結構,也可以聊網路框架等東西。我面試的公司中基本上百分之九十以上都問到了 Redis,只是深淺不一而已,比如喜馬拉雅問了 Redis 的資料儲存結構、rehash,bilibili 問了 Redis 的事務與叢集。

三、考察專案經驗

只問一些做過的業務或者專案經驗,這類公司他們招人其實對技術要求不高,除非是資深及主管級開發。只要你過往的專案與當前應聘職位匹配,可以過來直接上手幹活就可以了,當然薪資也就不會給很多。比如遊戲公司會關心你是否有某某型別的遊戲開發經驗、股票類公司會關心你是否有過證券或者交易系統的開發經驗等。

業務開發哪裡都能找到,真正重視技術的公司,應該是廣大做技術尤其是初中級開發的朋友更為關注的。

不靠譜型公司

面試過程中,其實還會發現一些不靠譜的公司,我遇到的大致有四類:

裝 X 忽悠型公司

面試過程冗長繁瑣,我面試的有一家公司就是這個樣子,先是一輪長長的電話面試,然後是五輪技術面試,前三輪是刷 leetcode 上的原題,然後後幾輪面試官從基本的作業系統中斷、GDT、LDT、分表分頁機制問到上層高併發海量資料的架構。從外太空聊到內子宮,最後問具體職位做什麼時,要麼遮遮掩掩要麼原型畢露,或者討論薪資時,要麼面露難色要麼各種畫餅,但是實際就給不了多少薪水的。

佛性公司

全程面試官面帶微笑,問的問題你回答之後面試官也表示很贊同,但最後你就是沒通過。我猜測要麼公司不是很缺人,想觀望一下是否有合適的人才,要麼招聘資訊上開的薪資給不到。

老奶奶裹腳布型公司

其特點是面試週期長,往往第一輪面試通知你過了,讓你回去等上十天半個月後,給你打電話通知你來第二輪面試。面試要求穿正裝,帶好各種證件,面試前必須先查驗你的身份證、學歷證學位證,甚至是四六級考試證等等,麻煩至極。即使你一路過關斬將過了終面,薪資也給不了多少。大家都是要養家餬口的,都是忙著找工作,誰有時間和你耗上十天半個月呢?

不尊重人的公司

我這裡說的不尊重人,不是指的是面試過程中對你人身攻擊,而是不根據你的工作年限和經驗隨意安排面試官。舉個例子,比如你工作十年,你去面試一個技術總監的職位,對方公司安排一個工作不滿兩年的部門職員作為面試官,這個面試官如果是走過場可以理解,但是非要和你糾結一個如二進位制位移、現代編譯器要不要在子類解構函式前加 virtual 關鍵字這些技術細節就沒必要了。還有一類就是故意問一些刁鑽的問題,或者全場都心不在焉、玩手機、漫不經心的面試官,比如問你 TCP 協議頭有多少個欄位,每個欄位是幹啥的。遇到這一類面試官我的經驗就是要麼婉拒,要麼直接懟回去。

技術之外的關注點

除了技術上的東西,面試中還有其它方面需要思考,這些東西有時候可能比你直接面試通過一家公司還重要,因為其中有一些是關係到你整個職業發展的:

第一,如果你的工作年限不長,尤其是渴望在技術方面有一定的造詣,那麼你首先考慮的應該是新的單位是否有利於你技術上的成長,而不是把眼光放在三五千的工資差距上。另一方面,如果想轉行的同學,比如從客戶端轉伺服器,從 C++ 轉 Java,那麼不要因為薪資突然變低而拒絕這種陣痛,要把目光放長遠一點。

第二,一些公司雖然招聘資訊上寫了最多能給到多少多少,但實際上即使你全程面試下來都很完美,可能最終也會因為在招聘資訊範圍內提出的薪資要求“太高”而不被錄取。

第三,一些根本不想去的公司,如果你有時間的話,去面試積累下經驗也不是什麼壞事。

第四,面試的時候,同時也是你在考察面試官,一般面試官問你的問題,你能回答出來的在百分之八十左右,這樣的公司可以考慮去入職,你進去的話可能才會在技術上有一些提升。如果你全場秒殺面試官的題目,那麼一旦你入職,你的技術天花板可能也就在那裡了。

第五,面試的時候聊清楚你將來的職位內容,避免進去客串一些不想做的工作。

第六,遇到不會的面試題,不要直接就否定自己,可以嘗試著去和麵試官溝通一下,或者要求給點提示或者思路。

第七,不要輕視筆試中的一些數學智力題目,認真作答,試問演算法不也是數學智力題嗎?

第八,自信一點,每個人的經歷和經驗都是獨一無二的,面試的時候,一些特定領域的問題,回答不出來也不要太在意。

上邊這些就是我經過與 30+ 家公司過招,引發的關於面試的思考,希望對閱讀的朋友有所幫助。

因為個人經驗能力有限,而且限於篇幅,很多地方也不便詳細展開,讀者如果有什麼想法或者指教,歡迎交流探討。

作者介紹

張小方,資深開發工程師,目前在某大型旅遊網際網路公司任技術專家,專注於高效能伺服器的研究與開發。

本文系作者投稿文章,歡迎投稿。投稿要求見:

https://my.oschina.net/editorial-story/blog/1814725

可參考已釋