最近 Google VO 高頻出現這道 Config Diff 系統 題目,看似簡單的字典比較,實則是一道 層層遞進的工程設計題。
很多同學第一版寫完就鬆了口氣,結果被 3 輪 Followup 打得措手不及。今天 oavoservice 帶你完整拆解這道題,從基礎版到生產級實現。
📋 題目描述
給定兩個嵌套字典 left 和 right,比較它們並輸出一個包含三個部分的結果字典:
- added — 右邊新增的 key
- deleted — 右邊刪除的 key
- edited — 兩邊都有但值不同的 key
🎯 面試流程還原
第一步:Clarify(關鍵!)
面試官一開始會讓你 clarify,這裡一定要問清楚:
- Q: Value 可以是嵌套字典嗎?
- A: 一開始不需要考慮 nested,所有 value 都是基本類型
- Q: Value 可以是 list/array 嗎?
- A: 不需要考慮
💡 oavoservice 提醒: Clarify 階段決定了你的第一版程式碼複雜度。先從簡單版本開始,為後續 Followup 留出空間。
✅ 基礎版:扁平字典比較
思路
三次遍歷:
- 遍歷
left的 key,找 deleted 和 edited - 遍歷
right的 key,找 added
oavoservice 滿分解法
def config_diff(left: dict, right: dict) -> dict:
result = {
"added": {},
"deleted": {},
"edited": {}
}
# 找 deleted 和 edited
for key in left:
if key not in right:
result["deleted"][key] = left[key]
elif left[key] != right[key]:
result["edited"][key] = {"old": left[key], "new": right[key]}
# 找 added
for key in right:
if key not in left:
result["added"][key] = right[key]
return result
範例
left = {"a": 1, "b": 2, "c": 3}
right = {"a": 1, "b": 5, "d": 4}
# Output:
{
"added": {"d": 4},
"deleted": {"c": 3},
"edited": {"b": {"old": 2, "new": 5}}
}
複雜度分析
- Time: O(n + m),n 和 m 分別是 left 和 right 的 key 數量
- Space: O(n + m),儲存結果
測試用例設計
面試官會問你如何設計 test case:
- 空字典 —
{}, {}→ 全空 - 完全相同 —
{"a": 1}, {"a": 1}→ 全空 - 完全不同 —
{"a": 1}, {"b": 2}→ deleted + added - 只有 edited —
{"a": 1}, {"a": 2} - 混合情況 — added + deleted + edited 都有
🚀 Followup 1:支援 Nested Dictionary
題目變化
現在 value 可以是嵌套字典,需要遞迴比較。
核心思路
- 如果兩邊都是 dict → 遞迴比較
- 如果一邊是 dict 一邊不是 → 視為 edited
- 其他情況 → 基礎比較邏輯
oavoservice 滿分解法
def config_diff_nested(left: dict, right: dict) -> dict:
result = {
"added": {},
"deleted": {},
"edited": {}
}
all_keys = set(left.keys()) | set(right.keys())
for key in all_keys:
left_val = left.get(key)
right_val = right.get(key)
if key not in left:
# Added
result["added"][key] = right_val
elif key not in right:
# Deleted
result["deleted"][key] = left_val
elif isinstance(left_val, dict) and isinstance(right_val, dict):
# 遞迴比較嵌套字典
nested_diff = config_diff_nested(left_val, right_val)
# 只有非空的部分才加入結果
if any(nested_diff.values()):
result["edited"][key] = nested_diff
elif left_val != right_val:
# 值不同(包括類型不同)
result["edited"][key] = {"old": left_val, "new": right_val}
return result
範例
left = {
"db": {"host": "localhost", "port": 3306},
"cache": {"enabled": True}
}
right = {
"db": {"host": "prod.db.com", "port": 3306},
"cache": {"enabled": True, "ttl": 300}
}
# Output:
{
"added": {},
"deleted": {},
"edited": {
"db": {
"added": {},
"deleted": {},
"edited": {"host": {"old": "localhost", "new": "prod.db.com"}}
},
"cache": {
"added": {"ttl": 300},
"deleted": {},
"edited": {}
}
}
}
🚀 Followup 2:支援 List 作為 Value
題目變化
現在 value 可以是 list,如何處理?
討論要點(面試官想聽的)
這裡面試官不一定要你實現,更想聽你的設計思考:
簡單方案:整體比較
- 兩個 list 直接
==比較 - 不同就算 edited,記錄 old/new
- 兩個 list 直接
複雜方案:元素級別比較
- 需要定義「相同元素」的標準
- 如果 list 元素是 dict,可能需要 ID 欄位來匹配
- 類似 React 的 key 概念
順序敏感 vs 順序無關
[1, 2, 3]vs[3, 2, 1]是否相同?
oavoservice 推薦實現(整體比較版)
def config_diff_with_list(left: dict, right: dict) -> dict:
result = {"added": {}, "deleted": {}, "edited": {}}
all_keys = set(left.keys()) | set(right.keys())
for key in all_keys:
left_val = left.get(key)
right_val = right.get(key)
if key not in left:
result["added"][key] = right_val
elif key not in right:
result["deleted"][key] = left_val
elif isinstance(left_val, dict) and isinstance(right_val, dict):
nested_diff = config_diff_with_list(left_val, right_val)
if any(nested_diff.values()):
result["edited"][key] = nested_diff
elif isinstance(left_val, list) and isinstance(right_val, list):
# List 整體比較
if left_val != right_val:
result["edited"][key] = {"old": left_val, "new": right_val}
elif left_val != right_val:
result["edited"][key] = {"old": left_val, "new": right_val}
return result
🚀 Followup 3:Alternative Output Structure
題目變化
面試官可能要求換一種輸出格式,比如:
Flat Path 格式:
{
"added": ["cache.ttl"],
"deleted": ["old_key"],
"edited": ["db.host"]
}
或帶路徑的詳細格式:
[
{"path": "db.host", "type": "edited", "old": "localhost", "new": "prod.db.com"},
{"path": "cache.ttl", "type": "added", "value": 300}
]
oavoservice 滿分解法(Flat Path 版)
def config_diff_flat(left: dict, right: dict, prefix: str = "") -> dict:
result = {"added": [], "deleted": [], "edited": []}
all_keys = set(left.keys()) | set(right.keys())
for key in all_keys:
path = f"{prefix}.{key}" if prefix else key
left_val = left.get(key)
right_val = right.get(key)
if key not in left:
result["added"].append(path)
elif key not in right:
result["deleted"].append(path)
elif isinstance(left_val, dict) and isinstance(right_val, dict):
nested = config_diff_flat(left_val, right_val, path)
result["added"].extend(nested["added"])
result["deleted"].extend(nested["deleted"])
result["edited"].extend(nested["edited"])
elif left_val != right_val:
result["edited"].append(path)
return result
💡 面試官真正考察的是什麼?
這道題不只是考演算法,更考察:
- Clarification 能力 — 先問清楚再寫
- 遞迴思維 — 處理嵌套結構
- 邊界條件 — 類型不匹配、空值處理
- 工程思維 — 輸出格式設計、可擴展性
- Trade-off 討論 — List 比較的多種方案
🤯 常見翻車點
- 第一版寫太複雜 — 一開始就考慮 nested,浪費時間
- 遞迴沒處理好回傳值 — 嵌套結果為空時的處理
- 類型判斷遺漏 — 一邊是 dict 一邊不是的情況
- Followup 討論太淺 — List 比較只說一種方案
🚀 oavoservice:你的 Google VO 全程護航
Google 面試的特點是 層層 Followup,一道題能追問 30-45 分鐘。很多同學基礎版寫得不錯,但在 Followup 階段被問懵。
oavoservice 的 VO 即時輔助 可以幫你:
✅ 即時思路提醒 — Followup 方向預判
✅ 邊界條件提示 — 避免遺漏關鍵 case
✅ 討論要點準備 — Trade-off 分析支持
✅ 全程不干擾 — 適配 Google Meet / Zoom
不要讓一個 Followup 斷送你的 Google offer。
We consistently provide professional interview assistance services for major tech companies like Google, Meta, Amazon, and TikTok. Feel free to contact us if you're interested.
👉 立即添加微信:Coding0201
鎖定你的 Google 面試機會!