1. 程式人生 > >京東二面面經詳談

京東二面面經詳談

收到了京東的二面電話,我覺得這次面試有一定的廣度和深度,也和麵試官發生了一些爭論,是一次挺有意思的面試,遂詳細記錄之。

面經:

首先一上來面試官讓我做了一下自我介紹,經過了總共大約四五次電話面試,遇到這樣的問題已經是很多次了,但是我還是簡單表述了一下自己的技能棧就結束了,這個其實還可以再多說很多。

接著面試官問了一下我的學習過程(剛開始我沒搞懂面試官說的學習過程是什麼意思,後來瞭解到是自己的教育經歷)。然後我表達了一下自己大連理工大學軟體工程大三學生的狀態。

緊接著面試官問了下我的必修課有哪些。我說了下計算機網路、作業系統、資料結構與演算法、編譯原理(實際上當時我不太敢說編譯原理..感覺自己編譯原理確實已經忘很多了)。面試官對我的計算機基礎很感興趣,說我的筆試成績很高(京東之前有一個筆試),但是事實上京東那三道演算法題我只AC了兩道..頂天也只能是80了,可能選擇題做的比較好?於是面試官便開始考察起了我的計算機基礎。

面試官:常見的排序演算法瞭解嗎?

我:嗯,有一些瞭解。常見排序演算法可以分為三種時間複雜度,O(n+k),O(nlog2n),O(n^2)。O(n^2)的排序比如氣泡排序、O(nlog2n)的排序比如快速排序、歸併排序、二分插入排序,對於基於比較的排序演算法這個時間複雜度已經不能再低了,然後O(n+k)時間複雜度的排序比如桶排序、基數排序、計數排序(可能是這個地方複雜度說多了..面試官後面很大篇幅在問我時間複雜度)。

面試官:恩,我懂你的意思了,你對排序比較瞭解。你能說一下常見資料結構嗎?

我:我能以資料結構在Java中的體現了舉例子嗎?

面試官:我覺得emmm資料結構應該和語言無關吧...

我:那好吧,我以為您更想聽的是Java中的資料結構。常見的資料結構簡單的有連結串列、佇列、棧、二叉樹,稍微複雜一點的比如B+、B-、B*、紅黑樹、圖等。

面試官:那現在有10w個數字,你如何找出一個最大的那個數字呢?

我:堆(不知道怎麼會說出這個答案...很迷了)。(當時腦子有點抽,這個和後面幾個資料結構相關問題都說的挺迷)

面試官:blablabla說了一些,大致意思就是你不覺得這個時間複雜度有點高嗎?

我:(恍然大悟)實際上一次遍歷O(n)時間複雜度就可以找出最大值,用一個temp變數更新最大值,直到遍歷完所有數字。

面試官:(打斷了我)你不用說得太細,就是一次冒泡對吧。那10w數字如何找出最大的前20個數字呢?

我:這個地方我覺得可以使用最大堆(腦子抽了,為什麼是最大堆),可以在O(nlog2n)時間複雜度解決這個問題。

面試官:(感到奇怪)為什麼是最大堆呢?

我:可以建一個結點個數為20的最大堆,遍歷完所有資料,停留在堆中的結點就是top 20(我當時還是沒反應過來)。

面試官:那麼如果現在堆中的元素是1,2,3,...,20,你有一個19節點,你是放入還是不放入呢?

我:(還是沒有反應過來不是最大堆而是最小堆)我覺得可以將堆的根結點替換為19,然後調整位置,判斷最終19還在不在這個堆裡。

面試官:那你這個行為很尷尬啊,是不是每個結點你都需要放入堆中然後調整呢,這樣不覺得很不對嗎?

我:(還是沒反應過來)我覺得可以對這個最大堆的資料結構再進行一個封裝,新增入最大值和最小值屬性。

面試官:你能說一下最大堆的定義嗎?

我:(說實話我忘了我當時怎麼答的了,我說的很錯)

面試官:不對,最大堆的定義是這樣的,對於一個結點,其子節點值不大於他的值的完全二叉樹。對不對?

我:對...

面試官:(可能覺得引導不出我的正確答案了)你這個地方為什麼不用最小堆呢?每當需要檢視一個結點是否可以放入堆中,你直接看這個結點的值和根結點的值不就好了?

我:(恍然大悟..)嗯..是這樣的

面試官:那我們再來聊一下時間複雜度。你覺得平均來說,這個演算法的複雜度在多少?

我:建堆過程是O(n),之後放入每個結點調整的時間複雜度是O(nlog2n)。

面試官:(吃驚)為什麼建堆是O(n),你可以證明一下嗎?

我:(我也吃驚..那個一長串的求和公式化簡就是O(n)線性時間複雜度,這個在電話裡面說不清楚..聽到這個問題我楞了一下)我覺得這個問題很難說啊..但是可以用數學公式證明建堆過程的確是O(n)時間複雜度。

面試官:不對,建堆過程應該是O(nlog2n)時間複雜度,你如果硬要說是O(n)你可以證明嗎?

我:(這個怎麼在電話裡證明..有一些絕望)這個確實在電話裡很難證明,但是我覺得建堆確實是O(n)時間複雜度。

面試官:不對,我可以明確地告訴你,建堆是O(nlog2n)時間複雜度,你下來可以查一下。

我:(還是堅持建堆是O(n)時間複雜度)我還是覺得建堆的確是O(n)時間複雜度,當然我可能記錯了,但是我還是希望我們能下來確認一下,建堆的確是O(n)時間複雜度。

面試官:(我感覺面試官有些無奈了)你之前說過基於比較的排序時間複雜度上限是O(nlog2n),這樣的話豈不是你自己的話就自相矛盾了。

我:(我也有點懵了,覺得不應該再爭論下去,本質上還是自己知識不過硬)那可能我記錯了...

面試官:(突然一愣)是不是你說的建堆和我說的建堆不一樣,你是不是把建堆想成將20個元素放入到堆中但是不調整啊?那樣的確是O(n),但是我們這裡說的建堆是建好這個堆,不只是放進去。

我:(其實爭論了挺久,文字上看不出來這麼長的時間,我也有點動搖。本質上還是自己知識不過硬,我動搖了。)恩,那可能我建堆概念理解錯了。

(我下來仔細確認了這個建堆時間複雜度的問題,並不能說誰對誰錯。從空堆開始,依次插入各個關鍵碼,這個時間複雜度確實是O(nlog2n)。但是事實上有一種叫做篩選法的建堆方法,完全二叉樹大小為n,對於結點編號(從0開始作為第一個)為n/2-1的結點開始,判斷這個結點為根的的子樹是否滿足最大堆性質。滿足,不做調整;不滿足,做出調整。直到從n/2-1到結點0,整個完全二叉樹就變成了堆。時間複雜度為(2^i)*(log2n-i)從i=0到i=log2n進行求和,時間複雜度趨於線性,也就是O(n)。關鍵在於我們理解的建堆演算法出現了差異,所以對建堆複雜度的理解產生了一些不一樣的看法。但是由於本質上還是自己基礎不紮實,不敢繼續爭論下去,所以與真理擦肩而過...)

面試官:好,那麼現在我們達成了一個共識,建堆是O(nlog2n)時間複雜度,基於這個共識,我們來看下面的問題。10w資料,選出top 20,使用最小堆,時間複雜度是多少?

我:nlog2n。

面試官:詳細一點,比如n是多少?

我:100000log2 20

面試官:好,那麼如果前20個結點就是top20,時間複雜度是多少,以建堆時間複雜度為O(nlog2n)為基礎。

我:O(n)   (我這個回答很粗...)

面試官:(可能還是想引導一下我的正確答案)前20個結點建堆時間複雜度是多少?

我:20log2 20

面試官:那後面10w-20個結點呢?

我:O(n)

面試官:那總的時間複雜度是不是20log2 20 + 99980?

我:是的。

面試官:好,那麼我們接下來來看看計算機網路吧。你能說一下TCP的三次握手嗎?

我:(回答不詳細寫了,這個問題太常見了)....

面試官:那你能說一下斷開連線的四次揮手嗎?

我:(同 略)....

面試官:嗯,那麼比如我現在在瀏覽器敲入www.baidu.com,並且在搜尋框中輸入了詞條,點選搜尋,整個過程發生了什麼呢?

我:首先會進行DNS解析,將www.baidu.com解析為一個IP地址...

面試官:(打斷了我)什麼是DNS?

我:DNS是域名解析協議,執行在53埠號,主機會對代理伺服器發出遞迴的解析請求,然後這個代理域名解析伺服器會向其他伺服器發出迭代的解析請求。

面試官:好,那麼DNS是一定會發生的嗎?

我:不是的,存在瀏覽器快取、主機快取、伺服器快取,甚至還有Hosts檔案。

面試官:嗯,事實上www.baidu.com這樣的域名在代理伺服器一定是有快取的。那麼接下來發生了什麼呢?

我:域名解析出來了ip地址,同時也解析出來了埠號,主機就會向這個主機對於埠號建立連線,然後傳輸資料...

面試官:(打斷了我)等一下,這樣說的話所有使用者都是連線同一個主機,像www.baidu.com這樣的網站,一臺主機根本不可能讓他維持在6個9可用率上(這個我解釋一下,就是99.9999%的可用率)。

我:(這個我是真的不瞭解,但是我還是猜了一下)這個我可能不太瞭解,但是我覺得這個ip每次解析出來對應的一定不是同一臺主機,可能這是一個叢集,只不過是通過了DNS解析返回了不同的ip,或者做了反向代理什麼的。

面試官:blablabla(說了一堆東西....我其實記不太清了,但是我覺得面試官在這個方面應該是個專家...)

面試官:那現在假如建立了連線,伺服器端傳送完資料了,現在還要傳送,會怎樣呢?

我:我覺得這個主要是看這裡是長連線還是短連線。HTTP頭部有一個Connection欄位,當為close的時候為短連線,為keep-alive的時候為長連線。短連線則需要重新建立連線傳輸資料,否則就在當前連線上傳輸資料。

面試官:恩。你自己做過一些專案嗎?

我:blablabla (說了一點)

面試官:那現在給你一個真實場景,嘀嘀打車,你如果需要客戶下單,然後司機接單,你來實現,會怎麼實現?

我:(感覺可能面試官想考察我的高併發程式涉及思路)這是一個高併發場景嗎?

面試官:不,就考慮最基礎的。

我:那麼我覺得可以用生產者-消費者模型來實現...

面試官:(再次打斷了我)太粗糙了,說說細節。

我:將使用者的唯一標識、出發時間、出發地點、到達地點包裝成一個請求實體,放入到佇列中,然後司機從佇列中取出,返回一個已收到並且確認訂單的資訊。

面試官:(可能不太滿意,但是還是沒深究這個問題)那麼這個請求你用什麼協議來發送呢?

我:TCP

面試官:為什麼是TCP?HTTP不好嗎?比如現在微信,你覺得是用TCP嗎?

我:(不敢亂說)我覺得不一定,可能是其他協議,但是一定有自己的方法保證傳輸的可靠性。

面試官:(我感覺他不滿意)好吧,你後面想讀研嗎?

我:暫時沒有這個打算(後面說了一些自己的看法)。

面試官:你的實習時間可以是多長?

我:都可以。

面試官:恩,那我的問題就問完了,你有什麼想問我的嗎?

我其實在面試的過程中一直覺得面試官思維敏捷,知識面很廣,就忍不住問了一下面試官的履歷...結果發現面試官08年畢業,在外企幹了一段時間,自己創業過,百度幹過三年,騰訊幹過三年,後來積累了許多雲相關的知識,想要做一些相關工作。自己也拿到了阿里雲、騰訊雲、京東雲的offer,但是自己覺得阿里雲和騰訊雲都是體系很成熟了,於是選擇了京東雲,畢竟京東雲是從16年才開始認認真真做起來的。然後面試官和我說了一下他的看法,他覺得自己還是想在一個技術不是那麼成熟的地方認真做,而不是去一個技術很成熟的地方去修修補補。面試官在最後說了很多,確實也覺得面試官很有想法而且很厲害。最後面試就結束了。

感覺和這些優秀的前輩交流確實是一件很開心也很值得的事,通過一次面試得到了很多東西,看到了自己的不足,也看到了一位前輩的技術履歷和獨到的看法。

確認複試已通過,等候HR面。