PREP是我創建的一個助記符,用來幫助你記住解決白板編碼時需要涉及的步驟。它代表P:參數,R:返回,E:示例,P:偽代碼。
這個助記符是新的,但是其技術是經過實戰檢驗的。本質是一個對初學者比較友好版本的測試驅動開發,很適合編程挑戰者。
我們一起通過一個例子來學習PREP。例子中我將使用JavaScript語言,但是這項技術適用于任何編程語言。
面試官要求你寫一個函數,輸入一個句子并返回其中最長的單詞。你怎么做?
“P”就是輸入參數
大部分問題都會涉及編寫函數。在這一步中你需要確定你的函數需要輸入一些什么參數。并給它們取一個有意義的名字。
在這里,問題描述中“輸入”,“獲取”等關鍵字會給你指導,你也可以和面試官確認。在本例中“輸入一個句子”這一描述說明了這個函數應該輸入一個字符串參數。
所以你已經確定了參數的類型。但是參數名稱呢?聽起來也許很簡單,但是好的命名是一項至關重要的編程技巧,這需要練習。
你可以命名為“sentenceString”,但是命名為“sentence”相比更簡潔,并仍然清晰地表明我們處理的是字符串。
這只是第一步,你還需要為函數取一個有意義的名稱。在本例中“longestWord”既準確又具有描述性。好了現在你已經決定了這一點,你可以像這樣寫下一個函數:
function longestWord(sentence){
}
“R”代表返回
這個函數返回什么?一個數字?一個boolean值?還是一個字符串?
請牢記:函數的返回不等同于它在print或者log語句中顯示的內容(如果有print或者log輸出的話)。
同樣的,你可以查看問題的描述來確認返回內容。“返回最長的單詞”告訴你需要返回一個單詞,單詞也就是字符串。現在我們可以創建一個變量來代表返回值并放置到你的函數中。盡管你還不能返回一個正確的結果,但是你已經設置了一個正確的返回類型。你已經創建了一個占位符,這使得我們更容易進行下一步。
function longestWord(sentence){
var word = "placeholder";
return word;
}
“E”代表示例
即使是專家級的開發者,靜止的代碼也沒有運行起來的代碼好理解。你需要盡快的讓你的代碼跑起來并保持“活力“。你可以通過一個測試用例來給你的函數注入活力。
你知道如果給你的函數輸入”I saw a hippopotamus,“這個句子,只要正確運行它應該返回字符串”hippopotamus“。但是現在,你只需要看一下上一步設置的占位符來確認代碼已經設置正確并能夠跑起來。
function longestWord(sentence){
var word = "placeholder";
return word;
}
console.log(longestWord("I saw a hippopotamus"));
最后一個字母“P”代表偽代碼
現在是不是已經蠢蠢欲動準備編碼了,但是現在開始編碼會很容易陷入一些細節從而分散你解決整體問題的注意力。首先你需要設計一個策略,而偽代碼就是針對這種情形的策略。
偽代碼是一系列用口頭語言寫成的精確語句,描述了你需要做什么。
function longestWord(sentence){
// 用一個變量來保存目前為止最長的單詞
var word = "placeholder";
//將句子轉換成一組單詞,以便我們能夠遍歷每一個單詞。
// 遍歷每一個單詞。
//如果當前單詞的比目前為止最長的單詞還長,更新保存最長單詞的變量
// 在檢查完所有的單詞后,返回保持最長單詞的變量
return word;
}
//只要代碼運行正常,log應該輸出“hippopotamus”。現在它應該輸出“placeholder”
console.log(longestWord("I saw a hippopotamus"));
你已經完成了PREP。現在可以編碼了!
PREP的四個步驟已經幫助你清晰的表述了問題并且想到了怎么去解決它。事實上,框架搭好了,事情就成了一半了。大多數面試官會對你的有條不紊印象深刻。在這一點上,你的目標就是編碼并使你的樣例和測試通過。你可以對偽代碼的每一步編碼來實現這目標。
當你的代碼能夠跑起來并看到正確的輸出時,你已經獲得了可以運行的解決方案。
function longestWord(sentence){
// 用一個變量來保存目前為止最長的單詞.
var longestWordSoFar = "";
// 將句子轉換成一組單詞,以便我們能夠遍歷每一個單詞
var wordArray = sentence.split(" ");
var currentWord;
// 遍歷每一個單詞
for (var i = 0; i < wordArray.length; i++){
currentWord = wordArray[i];
// 如果當前單詞的比目前為止最長的單詞還長,更新保存最長單詞的變量
if (currentWord.length > longestWordSoFar.length){
longestWordSoFar = currentWord;
}
}
// 在檢查完所有的單詞后,返回保持最長單詞的變量
return longestWordSoFar;
}
// 只要代碼運行正常,log應該輸出“hippopotamus”
console.log(longestWord("I saw a hippopotamus"));
現在你已經完成了最困難的部分。你可以長舒一口氣,至少已經有一個可以運行的解決方案。這時,還有兩個問題需要思考:
- 是否存在一些邊界條件會使代碼崩潰?例如,你有考慮句末有句號的情形嗎?你需要為這些邊界條件寫更多的測試用例,在必要的情況下修改代碼。
- 你能夠把代碼整理得更整潔、或者更高效嗎?在貿然解決問題之前你應該與面試官討論讓他知道你的想法。
好了,就這么多。整個過程第一次看起來有點過于呆板,但是請相信我,這將成為第二自然--就像學習駕駛一樣。即使已經編程超過12年,在解決問題是我仍然會遵循這樣的順序。我可能會使用一些正式的測試框架,而不是像本例中這樣使用log輸出,但是其本質是一樣的。
現在你也來試一試?這里有幾個入門級的問題你可以用來練習,總體由易到難的順序:
- 1、加入你有一個字符串數組[ “adios”, “bye”, “ciao” ]。你的任務是寫一個total_characters函數,接收這個數組作為參數返回數組中所有字符的總和。
- 2、寫一個函數,拋硬幣n次,計算出現“人頭”的次數。
- 3、我們會給你一個包含兩個數的數組,返回這兩個數的和以及這兩個數之間的所有數。注意最小的數不一定總是在第一個。嘗試使用自己先使用PREP來完成框架,并且隨時都可以到這里確認并完成最后的解決方案。摘自Free Code Camp
PREP已經幫助數位學員通過了他們的代碼面試,我希望對你也有所幫助。Happy coding!
本文譯自有著12年編程經驗的 First Step Coding創始人Andy Tiffany 的經驗分享。
閱讀原文請戳When it comes to whiteboard coding interviews, remember to PREP