碼農唐磊 程序猿石頭
程序員
做者:Yura Shevchenko 來源:skypixel.com 面試
求職面試在絕大部分人來講都是必不可少的,本身做爲求職者也參與了很多面試(不管成功或者失敗),做爲技術面試官參與面試也有四五年的經驗,在面試過程當中也見識到了各類各樣的人(有厲害的,也有奇葩的)。在這裏也只想談談本身的一些見解,我說的不必定對,有不一樣的意見能夠留言參與討論。算法
面試原本就是一個雙向選擇的過程,面試官和候選人的地位本應該是一個平等的位置,面試官但願經過簡單的交流溝通能夠對候選人的技術,溝通等有必定了解進而肯定候選人是否匹配相應的職位。我的認爲一場成功的面試最好是可以讓求職者和麪試官都有必定的收穫(曾經也遇到過在某次面試後,HR 告訴我有候選人特地跟她反饋要表達對面試官的感謝,由於讓他頗有收穫,這固然仍是讓我感到很是高興的),每次參與面試,也但願本身能達到這個目標。對於候選人來講能從面試過程瞭解本身的不足或者交流探討面試問題;對於面試官來講能瞭解候選人的技術和項目,在交流探討中也是一次學習和鞏固。 另外面試可否經過最終強調的是職位匹配,一個蘿蔔一個坑,蘿蔔太大或過小都不必定合適。因此有時候面試沒經過並非候選人不夠優秀,也有多是候選人過於優秀(例如原本只想招聘 P6,結果來了一個 P8的候選人確定不合適)。編程
由於面試時間有限,1個小時(通常狀況)的時間很難去全面瞭解候選人的技術實力,所以在面試過程當中很難作到絕對的公平。舉個簡單的例子,面試官出一道題目,候選人 A 可能曾經作過或見過,因此可以比較輕鬆地回答出這個問題,而候選人 B 沒有作過,雖然不能答出讓面試官滿意的答案,但 B 提供了一些解題的思路,雖然最終並無答出這道題目,這就必定說明候選人 B 比 A 差麼? 並非吧。vim
下面就從這道題目提及,這道題目是我在過往的面試中常常考察的一道題目。網絡
實現一個函數,完成 開根號 的操做,方法簽名以下:數據結構
double sqrt(int v, double t)
要求:框架
其實剛開始,我認爲這道題目比較簡單,至少在給予提示後,理想狀況下大部分一線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) 的例子都得不到預期結果。
可以到達這一個步驟的人已經較少了,若是你有較全測試用例和邊界條件的判斷,再加上後面的結束條件可以正確,基本上這道題目就算滿意了。
本質上講,這個算法就是一個迭代逼近的過程,用二分的思路後,關鍵就在於何時結束。 題目中已經給了偏差條件 圖片 ,難點在於其中的圖片不知道,不太方便直接進行計算判斷。很多人用一個另外的結束條件來進行了判斷即: 圖片 ,其實這兩個條件是不同的。
對於這個結束條件,你有什麼見解嗎? 能證實你的想法嗎?
固然本題還有一些其餘的數學解法,例如用牛頓迭代法,梯度降低法(最速降低法),泰勒公式展開等等。若是候選人能想到這些,說明他仍是有必定數學基礎的,若是願意可讓他講講。(考察這道題目本意並非指望候選人用這些數學方法解的。)
對於這道題目,你有什麼比較好的思路嗎? 歡迎留言參與討論。
本文題目是「從一道面試題談談一線大廠碼農應該具有的基本能力」,其實,上面大部份內容只談到了這道題目自己(也穿插了一些對這道題目的分析和理解)。上述題目的場景是社招面試中的,對於這樣的題目來講校招的反饋會更好。由於在校生可能對於工做經驗,項目經驗等比較欠缺,因此只好用一些比較固定的算法來面試進行篩選(本質上跟學校考試沒有太大的區別)。
但這種相似的題目在社招場景下就徹底不適用嗎?社招的的同窗寫不出來就有很充分的理由嗎?或許你在工做場景中不會遇到實際這種題目,但我其實想表達的是,做爲在最前線寫代碼的碼農,在別人講解了二分算法且本身也能理解的狀況下,能寫出這個二分算法應該不算太難?至關於一個需求,你們討論了算法實現和解法,須要你把它變成能跑的 code 而已。
其實這篇文章最開始叫「從一道面試題談談一線碼農應該具有的基本能力」,幾年前發出來被噴了,後來想一想彷佛被噴也有點道理,由於在平常有些場景下,「複製粘貼」工程師貌似也夠用了,遇到問題有更高水平的人來幫你解決就行,你們都同樣的話,怎麼體現高手水平呢?但從用人單位角度想,固然是更但願招聘更加優秀的選手,怎樣體現優秀呢?候選人基數太大,怎麼篩選,其實也就「高考」同樣嘛,經過「考試」擇優錄取而已。
咱們就不去討論是否每一個寫代碼的人都須要有這樣的能力(好像答案也是顯而易見並非)。但我建議我們一線的程序員們(特指有上進心的一線程序員)應該對一些基本的數據結構和算法有所瞭解,對常見的算法複雜度有所瞭解? 或者至少應該有這樣的追求吧?好比二分搜索複雜度爲何是 。以前遇到過好比有的候選人,Java 開發七八年經驗了,簡歷描述精通 Java,但不清楚 ArrayList, HashMap 內部大概是怎麼作的(我理解,無論什麼都須要知道大體的實現原理纔有可能去優化遇到的各類性能問題吧?)。還有什麼熟練掌握 Vim,結果其實就是熟練掌握如何打開和關閉 vim。還有的候選人口頭表達頭頭是道,結果落實到寫代碼就根本下不了筆。
有時候感受大部分程序員都被大量的需求壓迫着,被產品經理催促着,倉促地碼着繁瑣的業務代碼,不斷的改着 Bug 又引入新的 Bug。 業務代碼重要麼,固然重要(代碼就是服務於具體業務的),但同時也仍是但願咱們不要拋棄一些基礎的東西,多培養一下咱們的編程素養。咱們在用編程語言,利用各類工具來實現咱們想要達到的目的的時候,能作到「知其然,知其因此然」豈不更好?