與我一個team的某外國人(以下簡稱N)在今天遇到了一個不錯的問題,就問我要來一次模擬面試嗎。雖然同為實習生,但N被面試經驗豐富,而且還去面別人。於是果斷說了句,sure。問題如下(為了方便觀看,翻譯成中文了):
有一個整數數組,一個該數組的子數組SA,求一個滿足以下條件的子數組
1. 子數組包含SA
2. 子數組的和要為0
3. 子數組要小
4. 子數組要連續
例如,數組為{1, -1, 2, 8, -9, 4, 0},SA為{8,-9},即數組從下標為3(包含)到下標為5(不包含)的部分(下標從0開始算)。那么所求的子數組是{-1,2,8,-9}。
>_< 往下看之前,可想象下如果自己是面試者,會怎樣做。idea部分約為10min >_<
我當時的策略是先給一個簡單粗暴的方法,然后再慢慢改。那個簡單的方法是枚舉包含那個子序列的每一個序列,復雜度為O(n^2)。結果在改進為O(nlogn)的方法時,總改不成功。無奈之下,只好放棄改進這個方法。之后想到了從初始子序列左邊開始枚舉,再枚舉子序列右邊的,最后再計算左右兩邊相交的情況。枚舉左邊或者右邊,只需O(n),但計算相交,卻要O(n^2)。想用類似於分治的方法來減下復雜度,還是不成功。之后向N問道,滿足條件的子序列是否一定存在。N回答說可以假設一定存在,也可以假設不一定存在。為了方便起見,我選擇假定一定存在並且唯一。於是提出了將初始子序列(假設和為sum)去掉,在剩下的數組中尋找和為-sum的連續子序列。結果在時間到之前也沒優化成功。
進入Coding階段。N讓我實現那個先枚舉左邊和右邊,然后計算左右相交的算法。幾分鍾后,N看了下,說了句Good。面試就結束了。
最后向N要了一些feedback,總結如下:
a. 開始時要先向面試官確認每個條件。例如:這個序列一定存在嗎?設計的算法一定要是確定性算法嗎?子序列要小是指求最小子序列嗎?這是非常重要的,因為有時面試官會故意將某些條件說得模糊點,然后期待面試者問清楚;有時某些條件能直接引導你想到新的idea,例如算法可以是隨機算法嗎。
b. idea階段主要觀察面試者的思維是否夠活躍。能給出最優的想法就最好,當給不出時,就要給出盡量多的方法。這些算法的復雜度可以相同,但idea要不同。例如上面的順序枚舉和先枚舉左右兩邊,然后計算相交就可以認為是兩個idea了。換句話來說,如果優化的把握不大,那么最好的做法是先給出若干個復雜度相同但idea不同的算法,然后再從中選擇一個進行改進。這樣做可以讓你在想不到最優的算法時,還能保持一個不錯的評價。像我上面那樣做,就比較吃虧了。
c. Coding階段主要觀察面試者進行簡單的coding能否一次成功,即當寫完時,幾乎沒有bug。這個只能靠平時的努力了。然后在Coding時,注意提醒下自己現在是面試,不要將變量名或者函數名不要起得太長就行了。不過,最好的做法還是問下面試官想看什么樣的代碼吧。