Uber VO 真題複盤|二叉搜索樹第k大元素 + 反向中序遍歷完整解析
導讀:Uber 的 VO(Virtual Onsite)面試經常考察樹形資料結構的深度理解。「二叉搜索樹中找第k大元素」是一道經典題目,考察候選人對 BST 性質的理解、遞迴遍歷的掌握,以及問題澄清和優化能力。
本文深度複盤這道真題,包括面試中的關鍵澄清、算法設計、複雜度分析,以及如何處理多個k值的優化方案。
📌 題目描述
問題陳述
給定一個二叉搜索樹(BST)和一個正整數 k,找到二叉搜索樹中的第k大元素。
示例:
10
/ \
4 20
/ \ \
2 5 40
如果 k = 3,輸出應為 15
如果 k = 5,輸出應為 4
排序順序:40 > 20 > 15 > 10 > 5 > 4 > 2
🎯 面試中的關鍵澄清
澄清 1:樹的大小假設
問題:是否可以假設二叉樹至少包含 k 個元素?
面試官回答:是的,可以假設樹至少包含 k 個元素。
意義:這簡化了問題,我們不需要處理 k 超出範圍的情況。
澄清 2:錯誤處理
問題:如果樹的大小小於 k,應該返回什麼?
候選人建議:返回 -1 可能會引起混淆,因為 -1 可能是樹中的有效值。建議拋出一個錯誤。
面試官同意:這是一個很好的觀察,展示了候選人的細緻思考。
澄清 3:資料結構定義
問題:是否需要定義樹節點類?
面試官回答:是的,需要定義 TreeNode 類,以確保候選人能夠構建和操作二叉搜索樹。
💡 算法設計
核心思想:反向中序遍歷
利用 BST 的性質:中序遍歷得到升序序列。因此,反向中序遍歷得到降序序列。
反向中序遍歷順序:右子樹 → 根節點 → 左子樹
詳細步驟
以示例樹為例,找第 3 大元素:
1. 從根節點 10 開始,向右移動到 20
2. 繼續向右移動到 40
3. 40 沒有右子節點,訪問 40(計數 = 1)
4. 回到 20,訪問 20(計數 = 2)
5. 移動到 20 的左子節點 15,訪問 15(計數 = 3)✓ 找到!
Python 完整代碼
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class KthLargestFinder:
def __init__(self):
self.count = 0
self.result = None
def kthLargest(self, root, k):
"""
找到 BST 中第 k 大的元素
時間複雜度:O(n)(最壞情況)
空間複雜度:O(h)(遞迴棧深度)
"""
self.count = 0
self.result = None
self._reverse_inorder(root, k)
if self.result is None:
raise ValueError(f"樹中沒有第 {k} 大的元素")
return self.result
def _reverse_inorder(self, node, k):
"""反向中序遍歷"""
if node is None:
return
# 先遍歷右子樹(較大的值)
self._reverse_inorder(node.right, k)
# 訪問當前節點
self.count += 1
if self.count == k:
self.result = node.val
return
# 再遍歷左子樹(較小的值)
self._reverse_inorder(node.left, k)
# 測試用例
if __name__ == "__main__":
# 構建示例樹
root = TreeNode(10)
root.left = TreeNode(4)
root.right = TreeNode(20)
root.left.left = TreeNode(2)
root.left.right = TreeNode(5)
root.right.right = TreeNode(40)
finder = KthLargestFinder()
print(f"第 3 大元素:{finder.kthLargest(root, 3)}") # 輸出:15
print(f"第 5 大元素:{finder.kthLargest(root, 5)}") # 輸出:4
📊 複雜度分析
| 指標 | 複雜度 | 說明 |
|---|---|---|
| 時間複雜度 | O(n) | 最壞情況需要遍歷所有節點 |
| 空間複雜度 | O(h) | 遞迴棧深度等於樹的高度 |
優化:如果樹是平衡的,h = O(log n),則空間複雜度為 O(log n)。
🔥 擴展問題:多個 k 值
問題
如何在一次遍歷中找到多個 k 值對應的元素?
解決方案
def kthLargestMultiple(root, k_values):
"""
一次遍歷找到多個 k 值對應的元素
時間複雜度:O(n)
空間複雜度:O(h + m),m 為 k 值的個數
"""
k_set = set(k_values)
max_k = max(k_values)
results = {}
count = [0] # 使用列表以便在嵌套函數中修改
def reverse_inorder(node):
if node is None or count[0] >= max_k:
return
# 遍歷右子樹
reverse_inorder(node.right)
# 訪問當前節點
count[0] += 1
if count[0] in k_set:
results[count[0]] = node.val
if count[0] >= max_k:
return
# 遍歷左子樹
reverse_inorder(node.left)
reverse_inorder(root)
return results
# 測試
result = kthLargestMultiple(root, [1, 3, 5])
print(result) # {1: 40, 3: 15, 5: 4}
🎓 面試要點總結
關鍵知識點
✅ BST 性質 - 中序遍歷得升序,反向中序得降序
✅ 遞迴遍歷 - 理解遞迴調用棧的深度
✅ 問題澄清 - 邊界條件、錯誤處理、資料結構定義
✅ 優化思路 - 從單個 k 值擴展到多個 k 值
Follow-up 問題
- 如果樹是平衡的,如何進一步優化?
- 如何處理樹中有重複值的情況?
- 能否用迭代方式實現反向中序遍歷?
- 如何在樹中頻繁查詢不同的 k 值?
🚀 VO 輔助策略
VO 面試
- 🎤 清晰講解:從 BST 性質開始,逐步推導反向中序遍歷
- 🔍 深度討論:準備好 Follow-up 問題的答案
- 🏗️ 系統思維:展示如何從簡單問題擴展到複雜問題
📚 相關資源
官方資源
學習資源
- LeetCode 230 - Kth Smallest Element in a BST
- LeetCode 235 - Lowest Common Ancestor of a BST
- Wikipedia - Binary Search Tree
社區討論
💼 需要專業輔助?
oavoservice 提供專業的 Uber VO 輔助服務:
✅ VO 輔助 - 實時提供思路和代碼提示
✅ 面試代面 - 資深工程師全程陪同
✅ 系統設計輔導 - 幫助你理解大廠思維
✅ 模擬面試 - 提前適應面試環境
聯絡方式
- 📱 微信:Coding0201
- 💬 Telegram:@OAVOProxy
- 📧 郵箱:[email protected]
- 🔗 官網:oavoservice.com
為尽快聯絡和評估,請注明:
- 面試公司:Uber
- 職位:SDE / New Grad
- 面試時間:具體日期
- 需求:VO 輔助 / 面試代面 / 模擬面試
發布日期:2026年3月16日
難度:⭐⭐⭐⭐ (中等偏難)
標籤:Uber, VO代做, VO輔助, 面試代面, 二叉搜索樹, 反向中序遍歷, 樹形DP, 系統設計
更新歷史:
- 2026-03-16:初版發布,包含完整解析和優化方案