從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

關於一線碼農的面試,我想說

求職面試在絕大部分人來說都是必不可少的,自己作爲求職者也參與了不少面試(無論成功或者失敗),作爲技術面試官參與面試也有四五年的經驗,在面試過程中也見識到了各種各樣的人(有厲害的,也有奇葩的)。在這裏也只想談談自己的一些看法,我說的不一定對,有不同的意見可以留言參與討論。

面試本來就是一個雙向選擇的過程,面試官和候選人的地位本應該是一個平等的位置,面試官希望通過簡單的交流溝通可以對候選人的技術,溝通等有一定了解進而確定候選人是否匹配相應的職位。個人認爲一場成功的面試最好是能夠讓求職者和麪試官都有一定的收穫(曾經也遇到過在某次面試後,HR 告訴我有候選人特意跟她反饋要表達對面試官的感謝,因爲讓他很有收穫,這當然還是讓我感到非常高興的),每次參與面試,也希望自己能達到這個目標。對於候選人來說能從面試過程瞭解自己的不足或者交流探討面試問題;對於面試官來說能瞭解候選人的技術和項目,在交流探討中也是一次學習和鞏固。 另外面試能否通過最終強調的是職位匹配,一個蘿蔔一個坑,蘿蔔太大或太小都不一定合適。所以有時候面試沒通過並不是候選人不夠優秀,也有可能是候選人過於優秀(例如本來只想招聘 P6,結果來了一個 P8的候選人肯定不合適)。

因爲面試時間有限,1個小時(一般情況)的時間很難去全面瞭解候選人的技術實力,因此在面試過程中很難做到絕對的公平。舉個簡單的例子,面試官出一道題目,候選人 A 可能曾經做過或見過,所以能夠比較輕鬆地回答出這個問題,而候選人 B 沒有做過,雖然不能答出讓面試官滿意的答案,但 B 提供了一些解題的思路,雖然最終並沒有答出這道題目,這就一定說明候選人 B 比 A 差麼? 並不是吧。

下面就從這道題目說起,這道題目是我在過往的面試中經常考察的一道題目。

動筆試試吧

實現一個函數,完成 開根號 的操作,方法簽名如下:

double sqrt(int v, double t)

要求:

  1. 不能調用系統庫函數,諸如 Math.sqrt(v) 之類的;
  2. 假設計算出的結果爲 r,要求滿足這個條件: ,其中 是真實的值, t 爲給定的一個誤差範圍,例如0.1等,即你計算出的值要在給定的誤差範圍內。
  3. 實現語言不限,你條件可以比上述更加苛刻,但不能寬鬆。例如調用你的接口 sqrt(9, 0.21) 返回值屬於 [2.79, 3.21] 這個區間的任意一個都滿足條件。

看到這裏,其實你可以 拿出筆和紙,嘗試解答一下,需要注意的是答案要滿足給定的誤差條件,歡迎溝通交流。其實這個題目是就是 leetcode 上原題稍加變化得到,做過的肯定覺得 leetcode 其他題目來說相對比較簡單。但沒做過也沒關係,如果在面試官的提示下能夠最終把這道題目解出來,在我看來也 OK 的,甚至有可能比刷過題記住解題答案的更好(當然刷過題目本身的肯定會圍繞這個題目穿插其他小問題的)。





從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

分割線

開始解答

其實剛開始,我認爲這道題目比較簡單,至少在給予提示後,理想情況下大部分一線coding的程序員都可以給出實實在在 code 的。然而“理想很豐滿,現實很骨感”,事實並非如此,然而在面試很很多人之後, 發現此道題目並不簡單,如果你能寫出來,說明你已經比很多人優秀了(至少在我過往的社招面試經歷中)。

當被問起這道題目之後,可能遇到的答案如下。

直接放棄

題目給出後,我一般首先明確候選人弄清楚了題目的含義然後會給一兩分鐘讓候選人先思考一下。

面試官:你有什麼思路嗎?求職者: 沒有啊。

可能候選人內心OS是: “你出這樣的題目是不是有病啊,明明有 lib 函數可以直接用的”。(之前同組有其他小夥伴確實有遇到這樣的候選人,語言雖沒這樣誇張,大意是:實際工作中會出現這樣的問題嗎? 我直接給你百度一個就行了)

在此強調,面試這道題目並不是想強調這個題目本身,期望以這道題目爲契機,考察候選人在分析問題和解決問題的能力,在交流過程中所體現的邏輯推理和思維方式等,當然最後也會看看實實在在的 Code,從編碼過程中看候選人的編程習慣,風格等等

也有候選人剛開始抱着那個約束誤差範圍的不等式研究 N 久,然後沒有然後了的。剛開始看這個條件當然好,但如果這個不等式沒有思路可以先放一放,沒必要在那苦熬。

面試官:這樣吧,如果我問題 根號10 等於多少?你怎麼回答?求職者:3點幾吧。面試官:你怎麼知道是3 點擊,因爲你知道9開根號是3,想象一下,你也可以完全用程序幫忙模擬你大腦思考的過程。求職者: 我再想想……

其實這裏是希望提醒候選人,我們首先是要解題,然後才考慮效率。即不管用什麼方法能夠給出一個答案的,這個時候候選人可能進入下一個階段了。

在實際工作場景中其實也是一樣,遇到一個問題,首先我們要想到的是如何解決這個實際問題,有了最基礎的解決方案之後再談優化。

暴力搜索

實際面試過程中也有人是直接到這個階段的。

先用一個循環找到 r,使得 r^2 是離給定 v 最近的平方數,即你希望算根號10 ,先找到3,因爲3^2=9 。

然後再用一個循環, 每次 r+=t ,直到 r^2 > v 爲止。

面試官:這個方法從理論上講, 是一個可行的方案,設想一下,如果我的精度要求很高,希望計算的 v 也很大,如 sqrt(v = 10000000, t = 0.000001) 之類的,調用你這個方法效率是不是很低,這個時候應該怎麼優化?求職者:這樣的話,我這個方法效率確實比較低,不過可以這樣優化,比如設置一個步長,一次迭代後,如果沒有達到預期,可以不斷修改這個步長來增大逼近真實值的速度,比如10倍誤差,100倍誤差等。

其實,在與候選人的不斷交流中可以看出候選人的 Problem Solving 的能力,這也是面試考察中的一點。例如關於上面問題的優化,也可能用於在實際工作中遇到的問題。

例如,我們在實際工作中可能經常會寫一些異步的回調通知接口等,這個接口可能是其他團隊維護的,有可能由於網絡問題等回調接口可能會失敗進而需要重試,對於重試的機制其實就可以借鑑上面的“步長”機制,第一次回調失敗, 我等待 1s 後重試,失敗再重試,也許間隔 1s 不太恰當,是否可以修改等待的步長,等待比如 5s,10s?等等再重試直到成功。爲什麼要這樣做? 也許對方 server 本來現在就處於峯值,你不停的重試不但沒有增加你接口調用成功的機會,反而增加對方 server 的負擔。

額,跑題了,回到這個問題本身,繼續

面試官:恩,這樣做確實可以優化。但從本質上講,假設我們不考慮誤差的話,這個題目其實就是在一個有序的列表裏面去搜索滿足條件的特定的值。剛剛你的方法是一個線性的搜索方案。常見的搜索還有其他什麼嗎?

求職者:二分搜索?

面試官:對呀,你可以嘗試想想能否借用一下這個思路來解決這個問題。

 

二分搜索

當然,部分候選人提示二分後,就直接能夠 get 到點,並且能夠寫出二分大體框架,但可能結束條件寫的有點問題。

如果候選人還沒有思路,就會繼續

面試官:這樣理解吧,你剛剛的搜索整數部分的過程其實是線性的,一個一個數去暴力窮舉。藉助二分的意思就是,比如算 根號10,你搜索範圍是 [0, 10] (其實除了幾個數之外範圍可以更小[0, v/2],你能證明麼?)。

因爲5^2 = 25 > 10 , 所以 r 屬於[0, 5)

因爲(5/2) ^2 = 6.25 < 10 , 所以 r 屬於 (2.5, 5)

因爲(3.75^2 = 14.0625 > 10) ,所以 r 屬於 (2.5, 3.75)

繼續,如果你結束條件不太確定,可以暫時不管…

提示到這裏,感覺已經相對比較明顯了。

面試官: 你現在明白了嗎?求職者:明白了。面試官:那你寫一下代碼吧。

一個二分查找,算法思路都結合例子講一遍了,在候選人回答明白的情況下,理想當中,作爲一線開發者寫出來應該不成問題吧。然而…理想和現實還是有差距的。很多人都喜歡用遞歸寫,可是很多人遞歸裏面的最重要的結束條件都木有, 一些邊界條件等等都木有。所以一般情況下,代碼寫完後,我會讓候選人自己寫測試用例。

面試官:寫好了是吧,你寫幾個測試用例吧,假設這個接口是別人寫的,你應該從哪幾個角度去測試。求職者:sqrt(-4, 0.21),哎呀,我這裏忘了判斷了。改一下代碼。求職者:sqrt(0, 0.21),sqrt(4, 0.21)… 還有問題,再改改。面試官:……

爲什麼要別人提示要測試用例,纔去 check 自己寫的代碼的正確性呢。有的候選人寫的代碼,就不拿一些異常情況去 check,就用上面講的 sqrt(10, 0.21) 的例子都得不到預期結果。

能夠到達這一個步驟的人已經較少了,如果你有較全測試用例和邊界條件的判斷,再加上後面的結束條件能夠正確,基本上這道題目就算滿意了。

關於結束條件

本質上講,這個算法就是一個迭代逼近的過程,用二分的思路後,關鍵就在於什麼時候結束。 題目中已經給了誤差條件

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

,難點在於其中的

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

不知道,不太方便直接進行計算判斷。不少人用一個另外的結束條件來進行了判斷即:

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

,其實這兩個條件是不一樣的。

對於這個結束條件,你有什麼看法嗎? 能證明你的想法嗎?

其他解法

當然本題還有一些其他的數學解法,例如用牛頓迭代法,梯度下降法(最速下降法),泰勒公式展開等等。如果候選人能想到這些,說明他還是有一定數學基礎的,如果願意可以讓他講講。(考察這道題目本意並不是期望候選人用這些數學方法解的。)

對於這道題目,你有什麼比較好的思路嗎? 歡迎留言參與討論。

常見問題

  1. 問:爲什麼題目中的 v 的類型是 int?答還真沒有理由,double 也無所謂,可能僅僅是因爲 leetcode 上原題計算的數是 int 吧。
  2. 問:我能正確答對這道題目就一定能通過這次面試嗎?
    答:強調一下,面試中考察這樣一個題目,並不是僅僅考察這道題目本身,不是說你將這道題做對了,就能通過面試,反之也不是說你沒做對這道題目就一定不能通過我們的面試。我們通過這道題目爲契機,希望考察的是候選人在分析問題解決問題的能力,在交流過程中所體現的邏輯推理和思維方式等,當然也有最後實實在在的 code。
  3. 問:這不是一道數學題目嗎,爲什麼程序員面試需要考察這樣的數學問題?
    答:同上,不是考察這道題目本身。另外,這也可以說不是一道數學題目,當然能用數學的方式解答。候選人能用數學的方式解答也算正確。
  4. 問:二分是這道題目的標準答案嗎?我能用其他解法嗎?
    答:同上,題目沒有標準答案,就算你用最暴力的算法搜索出來也是正確的解法,其他數學方法也對。
  5. :這道題目這麼簡單,牛頓迭代分分鐘秒掉,是不是太簡單了?
    答: 給你點贊。
  6. :這題目在說什麼,我搞了半天沒看懂,這TM是啥?
    答:如果確實認真看完整篇文章或跟面試官交流了那麼久,還是根本不明白這到底說的是一個什麼問題。那就別管了吧,隨他去吧,可能不是目標用戶而已。
  7. 問:我在實際工作中根本就不會遇到這樣的問題,你問這個有什麼用?
    答:同第2條答案。
  8. 問:你們公司還缺人麼,面試會考察哪些點?
    答:有興趣或者有其他問題可以戳我郵箱,郵箱地址:aUB0YW5nbGVpLm1l。 面試考察可能會涉及:CS 基礎/Code/數據結構和算法/解決問題/項目經驗/系統設計/溝通團隊協作等等。

結語

本文題目是“從一道面試題談談一線大廠碼農應該具備的基本能力”,其實,上面大部分內容只談到了這道題目本身(也穿插了一些對這道題目的分析和理解)。上述題目的場景是社招面試中的,對於這樣的題目來說校招的反饋會更好。因爲在校生可能對於工作經驗,項目經驗等比較欠缺,所以只好用一些比較固定的算法來面試進行篩選(本質上跟學校考試沒有太大的區別)。

但這種類似的題目在社招場景下就完全不適用嗎?社招的的同學寫不出來就有很充分的理由嗎?或許你在工作場景中不會遇到實際這種題目,但我其實想表達的是,作爲在最前線寫代碼的碼農,在別人講解了二分算法且自己也能理解的情況下,能寫出這個二分算法應該不算太難?相當於一個需求,大家討論了算法實現和解法,需要你把它變成能跑的 code 而已。

其實這篇文章最開始叫“從一道面試題談談一線碼農應該具備的基本能力”,幾年前發出來被噴了,後來想想似乎被噴也有點道理,因爲在日常有些場景下,“複製粘貼”工程師貌似也夠用了,遇到問題有更高水平的人來幫你解決就行,大家都一樣的話,怎麼體現高手水平呢?但從用人單位角度想,當然是更希望招聘更加優秀的選手,怎樣體現優秀呢?候選人基數太大,怎麼篩選,其實也就“高考”一樣嘛,通過“考試”擇優錄取而已。

我們就不去討論是否每個寫代碼的人都需要有這樣的能力(好像答案也是顯而易見並不是)。但我建議咱們一線的程序員們(特指有上進心的一線程序員)應該對一些基本的數據結構和算法有所瞭解,對常見的算法複雜度有所瞭解? 或者至少應該有這樣的追求吧?比如二分搜索複雜度爲什麼是

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

。之前遇到過比如有的候選人,Java 開發七八年經驗了,簡歷描述精通 Java,但不清楚 ArrayList, HashMap 內部大概是怎麼做的(我理解,不管什麼都需要知道大致的實現原理纔有可能去優化遇到的各種性能問題吧?)。還有什麼熟練掌握 Vim,結果其實就是熟練掌握如何打開和關閉 vim。還有的候選人口頭表達頭頭是道,結果落實到寫代碼就根本下不了筆。

有時候感覺大部分程序員都被大量的需求壓迫着,被產品經理催促着,倉促地碼着繁瑣的業務代碼,不斷的改着 Bug 又引入新的 Bug。 業務代碼重要麼,當然重要(代碼就是服務於具體業務的),但同時也還是希望我們不要拋棄一些基礎的東西,多培養一下我們的編程素養。我們在用編程語言,利用各種工具來實現我們想要達到的目的的時候,能做到“知其然,知其所以然”豈不更好?

附Java進階學習提升資料

每天2小時跟馬士兵學習Spring、高併發、Redis、Jvm、分佈式,坦克大戰,網約車項目,你終將成長爲架構師。

乾貨視頻,高級架構師最新java、spring、Redis、JVM、分佈式、高併發。要的留下私信我,一小時之內回覆。裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring,MyBatis,Netty源碼分析,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點高級進階乾貨的免費直播講解。

如何獲取?

關注我,私信回覆“馬士兵”即可獲取高清大綱,以上 spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構

如何私信?

(非頭條極速版)關注我後,在手機,點進我的主頁,主頁上方右上角有個私信,點擊私信,如何回覆關鍵字“馬士兵”即可精選馬士兵JAVA 高併發分佈式架構課程視頻

馬士兵多線程、高併發、設計模式、Redis、Spring、Jvm

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

網約車項目

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

需要資料直接關注留言私信“馬士兵”即可免費領取。

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

從一道面試題談談一線大廠碼農應該具備的基本能力,修改版

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章