← 返回博客列表
Uber

Uber VO 真題複盤|二叉搜索樹第k大元素 + 反向中序遍歷完整解析

2026-03-16

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 問題


🚀 VO 輔助策略

VO 面試


📚 相關資源

官方資源

學習資源

社區討論


💼 需要專業輔助?

oavoservice 提供專業的 Uber VO 輔助服務:

VO 輔助 - 實時提供思路和代碼提示
面試代面 - 資深工程師全程陪同
系統設計輔導 - 幫助你理解大廠思維
模擬面試 - 提前適應面試環境

聯絡方式

為尽快聯絡和評估,請注明:


發布日期:2026年3月16日
難度:⭐⭐⭐⭐ (中等偏難)
標籤:Uber, VO代做, VO輔助, 面試代面, 二叉搜索樹, 反向中序遍歷, 樹形DP, 系統設計

更新歷史