![]()
100的因數有7個,但面試官只關心你能不能寫出第8個判斷條件。這不是數學題,是效率意識的試金石。
去年某大廠算法崗終面,候選人簡歷光鮮,卻在手寫素數判斷時栽了跟頭。面試官后來復盤:「不是不會,是從沒想過循環邊界能少跑一半。」素數檢測這7行代碼,藏著兩個讓資深工程師翻車的細節。
因數檢測:為什么100的因數只有7個,不是8個?
先看基礎款。檢測100的因數,代碼邏輯直白得像超市收銀:從2開始試除,能整除就打印,除數自增直到等于被除數。
Python版本跑出來的結果:2、4、5、10、20、25、50。數一下,7個。
但100的因數明明有1、2、4、5、10、20、25、50、100,共9個。代碼只輸出7個,因為循環條件是div < num,主動排除了1和100本身。
這個設計很產品經理思維——排除 trivial cases(平凡情況),只關注「非平凡因數」。就像用戶畫像過濾掉極端值,代碼也在過濾無意義的邊界。
Java和JavaScript版本邏輯完全一致,連變量命名都沒換。這種跨語言的保守設計,說明算法層的東西,語法糖改變不了骨架。
素數判斷:那個讓循環少跑50%的符號
![]()
素數定義簡單:只能被1和自身整除。但代碼實現里有個反直覺的優化。
常規思路是從2試除到n-1。但原文代碼寫的是div <= no // 2,雙斜杠是整除,意思是「試到一半就停」。
為什么夠用了?假設n有個因數d大于n/2,那對應的配對因數n/d必然小于2。小于2的正整數只有1,而1不算「非平凡因數」。換句話說,大于n/2的因數,除了n本身,不存在。
這個優化把時間復雜度從O(n)砍到O(n/2)。在大廠面試里,寫出這個邊界的人,和寫div < no的人,會被分到不同的評級池。
flag變量的設計也很老派。Python用布爾,Java用boolean,都是先假設「是素數」,一旦發現因數就翻轉。這種「無罪推定」的邏輯,比直接return更符合早期編程教育的審美——單入口單出口,flag統一管控流程。
從教學代碼到生產環境:還差幾步?
原文代碼是標準教材寫法,但投到生產環境會被打回。
第一,輸入沒做校驗。int(input())在Python里遇到字符串直接崩潰,Java的Scanner倒是類型安全,但負數、0、1的邊界都沒處理。1不是素數,這段代碼會誤判。
第二,復雜度還能再砍。試除到√n就夠了,原理和「試到一半」類似:如果n=a×b,a和b至少有一個不大于√n。這個優化能把O(n)降到O(√n),面試寫出來是加分項。
![]()
第三,空間換時間的工業解法。埃拉托斯特尼篩法預處理,查詢變O(1)。但篩法代碼量翻倍,教學場景不會首選。
原文的定位很清晰:不是最優解,是可理解的解。就像產品經理畫原型,先保邏輯通順,再摳交互細節。
為什么大廠愛考這題?
素數檢測是算法面試的「瑞士軍刀題」。考察點分層:
基礎層:能不能寫出無bug的循環。很多人死在邊界條件,<和<=搞混,或者忘記自增死循環。
進階層:知不知道優化到n/2。這題篩的是「有沒有主動思考過效率」的人。
拔尖層:能不能推到√n,甚至說出篩法。到這一層,面試官開始聊項目深度了。
某頭部云廠商的校招數據:算法題通過率約35%,但素數相關變體題的區分度最高——會的人分都高,不會的人理由各異。
代碼風格也在考察范圍內。原文三版代碼,Python用蛇形命名(num_div),Java用駝峰(numDiv),雖然示例里沒體現,但變量命名的一致性,是工程素養的暗線指標。
最后留個思考題:如果輸入是10^12級別的數,這段代碼需要跑多久?√n優化后呢?篩法預處理10^6以內的素數再查詢呢?三種策略的 trade-off(權衡),對應三種不同的系統架構思維。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.