2014年1月7日Google實習電面

Google兩輪電面,兩個面試官都根據我的背景聊了下big data。

第一輪相談甚歡,就問了我一個題目:
給K個排好序的鏈表,總長度爲N,求如何合併成一個排好序的總鏈表。

我先談了談直接設K個指針從每個表頭開始掃,每次將k個數中的最小數加入總鏈表。然後我說這個顯然沒效率的,O(K*N)複雜度。
然後我說應該可以用分治法搞,兩兩merge,複雜度爲O(logK*N)。

之後他問我雖然分治法快,但是相比第一種方法,有什麼缺點。
我猶豫了下,感覺沒發現什麼缺點,然後想歪了,在想是不是不好並行,不夠scalable?但是想了下感覺應該不是,然後就隨口用疑問的口吻丟出一句“space?”。美國人真nice,直接興奮的告訴我對啦!就是space,然後一串bulabula...


他之後說讓我選一個方法實現。我覺得要實現肯定得實現更有效的啦。
我寫了一段代碼,他沒發現bug,我還發現了一個小bug補上了,原來是忘記考慮輸入爲null的情況了。他說這個無所謂,我汗,感覺還沒我嚴謹。

之後問我,那你有沒有什麼方法減小空間的開銷。
我覺得這個很簡單,直接問輸入可以修改不?他表示ok。我就說,那我merge兩個鏈表的時候直接修改兩個鏈表結構,做成in place merge不就行了麼,無需額外空間開銷。他覺得這個方法可以,不過見我代碼是java寫的,表示in place merge在java中可不好實現哦,然後又bulabula一串,重點是雖然不好實現,但是仍然可以實現。我看他說得那麼興奮,瀑布汗啊。。。我本身就覺得這個問題分治法開銷本來就不大,要是我用c++或者按照LeetCode的ListNode定義,我本來就打算做成in place merge的,只不過他給我定義好接口了,用java API寫就沒寫成in place的。這也是在他問我缺點的時候我疑惑的原因。


第二面聽聲音是個年紀比較大的人,一開始還跟我討論校園文化,說他女兒對我校的鼓號隊感興趣,汗哪。。。

第一個問題是個經典問題,問給你millions of documents,如何sort這些string。之前還問我map reduce裏sorting是怎麼實現的。
我就說數據這麼大,用外排序唄,分成一個block一個block的排序,然後in place合併。他問了又些細節,我雖然見過這個問題,但是沒有想得那麼深入,感覺他對有些細節問題的回答不太滿意。
他還問了一個問題,說如果輸出的數據也要分塊的話,你是如何進行分塊操作的。我當時隨口一說,可以對每個string加一個data field叫size,做成類似於prefix sum的東西,不過這樣肯定不夠高效。
他說嗯,這個可以吧,沒讓我多想。不過事後想了下,發現這個問題太簡單了,之前自己還在project中實現過對文本文件的partition。就是先等長劃分,然後再調整劃分點的位置即可,通過尋找類似於'\0'這樣的字符就可以了。後悔死了,不過也怪他沒給我時間多想,直接轉到下個問題了。

第二個問題讓我打印出質數。
我問打印多少或者到哪個數爲止,他說不停打印就是了,感覺就是一股老子就是要讓cpu飛轉的氣勢。。。
這種數學類問題我完全沒有準備,沒什麼思路,就先從沒效率的方法開始說,對於每個數i,檢查前面從2到i-1是否存在一個數能夠把它除盡。
後來稍微想了下,說與其存儲之前所有從2到i-1的數,還不如存這些數最後分解的因子,畢竟之前遇到的因子肯定比之前遇到的數要少得多。
我再想了想,實在想不出什麼好方法,就補充道應該可以有數學方法,給出什麼複雜的數學公式搞定吧,不過我是學cs的,實在不知道額。他表示同意,說是有數學方法可以解決,不過他自己也看不懂,不要緊。
這樣我就放心了,然後他說那你就coding吧。

我的coding雖然沒什麼大的bug,但是代碼有些多餘的分析,他看了表示疑惑,覺得不夠精簡,因爲我一開始對每個合數都不停的讓之前的因子去除它,直到它不能再被除盡位置。如果剩下的值不爲1,就把剩下的值作爲新的因子,加入到所遇到的因子列表中。後來發現我忽略了一個重要的問題,每個所遇到的因子,必定爲之前遇到過的質數,所以這裏的一個不斷做除法的循環是完全沒必要的。我之後精簡了code,他覺得好多了。不過我覺得我的表現他應該不是特別滿意吧,畢竟一開始代碼不簡潔也不高效。

之後他問我如果一直這樣循環下去,會有什麼後果。我就說cpu一直飛速運行,直到內存溢出,因爲內存是不可能存儲下所有因子的。

他接着問有沒有什麼方法讓循環持續時間更長,找到更多的質數。
我說那就把這些因子分塊寫到硬盤上,然後每次遍歷所有因子的時候按一個block一個block的來。
他說能不能寫下code,我就納悶,不就加一個for循環麼。我直接加了個for each語句。
他看了下,說不高效,這樣每次檢查一個數是不是質數,都會遍歷所有的block,disk io開銷太大。
我沒聽懂意思,以爲說我寫for each的時候需要預先載入所有的block,我連忙說不是的,這些block是鏈表形式鏈接的,把for each語句改成了鏈表形式的遍歷。
他還是不滿意,畢竟我沒抓住重點。他說你應該把函數接口變下,輸入的數據不應該是一個數,而是一個block的數。
我恍然大悟,然後連忙接過話,說這個學過,本質就是編譯器課裏對嵌套循環的優化嘛,把多層循環分塊,提高data locality。然後解釋說我以爲他是讓我在降低time complexity上再下功夫,沒想到是讓我注重算法複雜度裏常數因子的開銷啊。他雖然表示同意,但是感覺這個人也許是年紀大的關係,沒第一個人活潑,語氣很低沉,給我感覺我的表現有些糟糕。

個人感覺第一面挺順利的,第二面表現有些不佳。看造化吧,發個面經求bless~
發佈了60 篇原創文章 · 獲贊 8 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章