2023/02/03~【Backend Engineer】未錄取
薪資範圍:~1.8M / 13 mth + bonus
主要產品為手搖飲料自動化機器人。以 Node.js 為主。共有三個產品,每個產品各有一位 FE 及 BE,另外所有產品共享 QA * 2、TPM * 1、UI/UX * 2。
第一題考列舉質數:
Q1. Return prime numbers <= n.
Followup 會請你分析時間複雜度、如何優化、怎麼進行單元測試。另外面試官有追問對於 Node.js 的熟悉程度,像是 與 的差異。
這一關包含系統設計類考題以及 Culture Fit 問題。
此面試階段結束前筆者有反問為什麼有現在這個職缺,面試官的回應是擴編並增加備援人力,會加入 Cloud 的產品線。另外詢問了目前開發遇到的難處,得到的回應是市場上找不到前例可以作為參考。
開頭先從概念性的問題交流:
接著是兩題 Live Coding,限定 Node.js,必須執行以驗證結果,過程中可以查詢輔助資源,但要分享螢幕畫面讓面試官看得到操作過程。
紅綠燈
Create traffic light function.Red light for 3 secondsGreen light for 2 secondsYellow light for 1 second
括號排列組合
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.Example 1:Input: n = 3Output: ["((()))","(()())","(())()","()(())","()()()"]
Example 2:Input: n = 1Output: ["()"]
Constraints:1 <= n <= 8
這題雖然可以使用 Recursion 快速滿足功能性,但是 Followup 被要求按照題目中的順序輸出結果。
function isPrime(m) { if (m % 2 === 0) { return false } // 2, 3, … m-1 for (let p = 3; p*p < m; p += 2) { if (m % p === 0) { return false } } return true}
function findPrimeNumbers(n) { if (n < 2) { return [] }
// m = 6, p = 3 let ans = [] // let, const for (let k = 2; k <= n; k++) { If (isPrime(k)) { ans.push(k) } } return ans}
function testIsPrime() { assertEqual(isPrime(2), true) assertEqual(isPrime(3), true) assertEqual(isPrime(4), false) for (let i = 4; i <= 16; i += 2) { assertEqual(isPrime(i), false, 'even numbers ...') } assertEqual(isPrime(-1), ?) assertEqual(isPrime(0), ?) assertEqual(isPrime(1), ?)}
function testFindPrimeNumbers() { assertEqual(testFindPrimeNumbers(5), [2, 3]) assertEqual(testFindPrimeNumbers(100), [2, 3, 5, ...])}
Followup 優化方式:
數學運算
檢查某個數字 是否為質數時,因數可以只檢查小於 的奇數即可,當然 這個數字本身要例外處理。
Lookup Table
假設 有上限,那麼只要空間足夠,其實可以用空間換時間,直接預算答案。
async function trafficLight() { async function sleep(s) { return new Promise(r => setTimeout(r, s * 1000)); } console.log('Red') await sleep(3) console.log('Greed') await sleep(2) console.log('Yellow') await sleep(1)}
trafficLight()
本題為 LeetCode 22. Generate Parenthesesopen_in_new。
function combinations(n) { if (n === 1) { return ["()"] } let result = new Set() const combs = combinations(n - 1) for (let comb of combs) { result.add(`(${comb})`) result.add(`${comb}()`) result.add(`()${comb}`) } return Array.from(result)}console.log(combinations(1))console.log(combinations(2))console.log(combinations(3))
Followup:請按照題目中的順序輸出結果。
最後僅寫出屍體:
function combinations(n) { let output = [] function backtracking(current, remainingRight) { if (remainingRight == 0) { output.push(current.padEnd(n*2-current.length, ')')) return } backtracking(`(${current}`, remainingRight - 1) backtracking(`${current}(`, remainingRight - 1) backtracking(`${current}()`, remainingRight - 1) } backtracking("", n) return output}
後來在 LeetCode 上面重刷,使用 Backtracking AC:
class Solution: def generateParenthesis(self, n: int) -> List[str]: output = [] def bt(current, remainingLeft, remainingRight): if len(current) == n * 2: output.append(current) return if remainingLeft > 0: bt(f"{current}(", remainingLeft - 1, remainingRight) if remainingLeft < remainingRight: bt(f"{current})", remainingLeft, remainingRight - 1) bt("", n, n) return output