2388 字
12 分鐘
👔 與 Google 的面試
2025-08-16
正在播放 放課後の音楽室

前言#

距離上次更新博客也大概過了一個月,這期間我一直想著要發布新文章,但是實在想不到要發甚麼。 直到最近我頻繁的回想起去年 2024 年 2 月份面試 Google 的經歷,所以我想趁著我還記憶猶新的時候,把當時的面試經歷分享給大家,也當作是一個紀錄。

我在這篇文章會分享我跟 HR 的談話過程,以及 5 輪面試中的第一輪 coding (編程)面試,我不分享其他四輪是因為面試過程大同小異,加上我還保留第一輪面試的代碼可以給大家看。

阿里山


為 Google 的面試做的準備#

為了準備 Google 的面試,前前後後花了一年的時間準備,一共刷了大約 350 題 LeetCode。還記得當時還在 ASML 工作的時候,下班不是健身就是在刷 LeetCode,甚至放假跟朋友去阿里山玩的時候還找了個咖啡廳在那刷題。

為了增加刷題的效率,我還在網上請了一個專門教 LeetCode 的家教,來監督我的刷題進度。

LeetCode總結


Google HR 的來電#

皇天不負苦心人,終於有幸在 2024 年 1 月份的時候接到了 Google 人資的來電,以下是我跟 HR 的對話:

人資:「我看了你的簡歷,你在 ASML 待了快兩年,待的時間也不算短了,怎麼會突然想換工作?」
我:「其實我當時畢業後就很想從事軟體業,我的大學畢業專題也是用 Python 寫的。只是當時沒有找到合適的機會,加上台灣半導體產業大舉徵才,所以選擇加入了 ASML。」
人資:「明白! 那你對 Google 的面試流程了解多少?」
我:「我知道 Google 有好幾輪面試,主要都是考 LeetCode 相關的題目,加上還有一輪行為面試用來評估所謂的 Googleyness?」
人資:「是的是的,你提到的行為面試就是 Google 的 G&L (Googleyness and Leadership) 面試。您目前累積的 LeetCode 題數大概是幾題呢?」
我:「大約 350 題。」
人資:「資料結構跟演算法都是熟悉的吧? 因為我們之前有遇到過一位面試者刷了 500 題的,但是他只刷單一類型的題目比如 linked-list,但是 tree, dynamic programming, stack/queue 都不太熟悉。」
我:「我懂你的意思,你不需要擔心,我都是按隨機來選擇題目的,妳剛剛提到的資結跟演算法我都有刷過。」
人資:「好的,那我就幫您安排第一輪面試了。先跟您說一下,第一輪面試會是 coding (編程),面試過程採用全英文,而且不能使用任何 IDE 或是查詢資料。 第一輪面試通過了之後會同時安排後續的 4 輪面試,其中的 3 輪會是 coding,還有 1 輪是剛剛提到的 "G&L Interview"。」
我:「第一輪面試是甚麼時候?」
人資:「距離今天大約兩週後。」
我:「好的! 那再麻煩您發面試邀請給我,謝謝。」

接著 HR 跟我講解了很多面試過程需要注意的事,以及可以怎麼準備 G&L 面試,在這對話過程中我可以感覺得出 HR 也很希望我可以通過面試。

我在面試前一週還約了幾個好朋友做了 4 次 mock interview (模擬面試),非常感謝 Phillip, Ivy, Jade, Alex, Yale, Steve, 還有其他綿羊群的同胞!


第一輪面試#

時間來到了第一輪面試,我當時面的是台灣 Google 的 Pixel Team 的一名工程師,他給我的印象就是斯文,而且表達能力跟英語能力非常突出。

我們雙方做了簡單的自我介紹後,他要求我分享螢幕畫面,然後出了一道題目給我:

Implement a restaurant waitlist data structure. It should support the
following features:
1. A party of customers can join the waitlist.
2. A party in the waitlist can leave the waitlist at any time.
3. The restaurant serves the first party whose size equals the empty table size (the table size is given as an argument).

接著是我跟面試官的對話紀錄:

面試官:「你先花點時間詳讀一下這道題目。然後說一下這道題會需要實現哪些函數?」
我:「首先會有一個 join 函數,然後 input 是 party_id 跟 party_size (party 的人數)。接著應該要有個 leave 函數,input 只需要 party_id。然後要有個 serve 函數,input 是 party_size,因為題目有說到餐廳會優先服務第一組 party_size 符合的 party。」
面試官:「好聽上去沒什麼問題,那麼你會用甚麼資料結構來解這道題?」
我:「我目前最直觀的想法是用 Doubly Linked-List 來解,每個 ListNode 就代表一個 party,然後每個 ListNode 會有 id 跟 size 這兩個屬性,分別代表 party_id 跟 party_size。」
面試官:「好,那你分析一下那三個函數的時間複雜度分別會是多少。」
我:「 join 的話會是 O(n),因為我需要先跑過整個 Linked-List,如果發現同一個 party 已經在裡面就回傳 -1,如果不在裡面,就新增 party 到 Linked-List 的尾部。」
面試官: 「對,那 leave 呢?」
我:「 leave 的話我需要跑過一遍 Linked-List 去找到符合的 party_id 並移除,所以時間複雜度也是 O(n)。 serve 的話也是同理,我需要跑一遍並找到符合的 party_size 並把它移除。」
面試官:「很好! 那就開始寫吧」

於是我就開始寫 code 了。在這過程中,我邊敲代碼邊用英文把我的思路講給面試官聽,大概過了 30 分鐘後,面試官接著說:

面試官:「我覺得你寫的 code 沒什麼問題。你目前 join 跟 leave 函數的時間複雜度是 O(n),有沒有甚麼方式可以優化它們?」
我:「我好像可以用 Hashmap/Dictionary 來優化,Dictionary 的 key 是 party_id,然後 value 是 party_id 對應到的 ListNode 物件,這樣我就不用跑一遍整個 Linked-List,直接用 map[party_id] 就能得到我要的 ListNode,我只需要確保新增/移除 ListNode 的時候去更新 map 就可以了。 這樣 join 跟 leave 函數的時間複雜度就能從 O(n) 降至 O(1)。」
面試官:「非常好!」

時間又過了 10 分鐘,我成功將我原先的代碼進行了優化,後續我問了面試官一些關於工作內容跟公司文化的問題,第一輪面試就告一段落了。

這裡順便附上面試的完整代碼:

# Implement a restaurant waitlist data structure.
# It should support the following features:
# 1. A party of customers can join the waitlist.
# 2. A party in the waitlist can leave the waitlist at any time.
# 3. The restaurant serves the first party whose size equals the empty table size (the table size is given as an argument).
# join(ID, size) -> Bool
# leave(ID) -> Bool
# serve(size) -> ID or -1 (if no matching size)
class ListNode:
def __init__(self, ID, size, prev=None, next=None):
self.ID = ID
self.size = size
self.prev = prev
self.next = next
class WaitList:
def __init__(self):
self.head, self.tail = ListNode(-1, 0), ListNode(-1, 0)
self.head.next = self.tail
self.tail.prev = self.head
self.map = dict()
def join(self, ID, size):
if ID in self.map:
return False
prev = self.tail.prev
node = ListNode(ID, size)
prev.next = node
node.prev = prev
node.next = self.tail
self.tail.prev = node
self.map[ID] = node
return True
def leave(self, ID):
if ID not in self.map:
return False
node = self.map[ID]
prev, next = node.prev, node.next
prev.next = next
next.prev = prev
del self.map[ID]
return True
def serve(self, size):
node = self.head.next
while node.ID != -1:
if node.size == size:
ID = node.ID
prev, next = node.prev, node.next
prev.next = next
next.prev = prev
del self.map[ID]
return ID
node = node.next
return -1
"""
time complexity:
join: O(1)
leave : O(1)
serve : O(n)
"""

隔天我接到了 HR 的來電,並告知說我的反饋非常正向,編程方面是肯定沒什麼問題,除此之外還在「表達能力」的部分被面試官賦予了 outstanding 的高度評價。

於是 HR 幫我安排了剩下的四輪面試,前前後後大約經歷了 3 週的時間,後來我被告知說我在其中一輪的 coding 面試並沒有達到預期標準。


總結#

雖然歷經了 Google 的五輪面試後最終沒有被錄取,但對我來說能受邀 Google 面試還是一項殊榮,畢竟 Google 一直是我心目中軟體界的標竿,而且我也很享受解 LeetCode 題目的過程。

以下是我透過刷題跟面試中領悟到的一些心得:

  • 遇到沒見過的題目會緊張很正常,畢竟 Google 的面試官就是想測試面試者在遇到新的問題會怎麼解決。
  • 在寫代碼之前一定要先跟面試官解釋你的思路,來確保你對題目的理解是沒問題的。
  • 不要一開始就試著想出最佳解,先從你最直觀的想法去解,哪怕是時間複雜度最差的 Brute-Force Solution (暴力解) 都沒關係,先求有再求好!
  • 在解題的過程中不要只是安靜的埋頭苦幹,在敲代碼之餘要把你的思路解釋給面試官,一方面是讓他知道你在想甚麼/做甚麼,另一方面是他才能夠適時給你引導,這個環節其實也是在考驗你團隊合作的能力。
  • 面試官給的提示跟引導一定要聽進去,他不會刻意去害你。
  • 雖然刷 LeetCode 多少還是需要一些天賦,但是隨著刷題數量的積累,你解題的速度一定都會有改善,所以千萬不要氣餒。

求職不容易,所以希望這篇文章能幫助到正在求職的你。

👔 與 Google 的面試
https://www.leowu.love/posts/與google的面試/
作者
Leo理央
發布於
2025-08-16
許可協議
CC BY-NC-SA 4.0