二分木の最小共通祖先(LCA)

二分木と BST で2つのノードの最小共通祖先(LCA)を見つけます。再帰アルゴリズム、BST 最適化、LCA の実世界での応用を学びます。

Algorithms

詳細な説明

最小共通祖先(LCA)

二分木における2つのノード p と q の最小共通祖先は、p と q の両方の祖先である最も深いノードです。ノードは自身の祖先になりえます。

一般二分木での LCA

LCA(root, p, q):
  if root is NULL: return NULL
  if root == p or root == q: return root
  left  = LCA(root.left, p, q)
  right = LCA(root.right, p, q)
  if left != NULL and right != NULL: return root
  return left if left != NULL else right

BST での LCA(最適化版)

BST では順序性を活用できます:

LCA_BST(root, p, q):
  if p.value < root.value and q.value < root.value:
    return LCA_BST(root.left, p, q)   // 両方とも左部分木に
  if p.value > root.value and q.value > root.value:
    return LCA_BST(root.right, p, q)  // 両方とも右部分木に
  return root  // 分岐点 — これが LCA

この BST 版は一般二分木版の O(n) に比べ、O(h) 時間と O(h) 空間(反復的なら O(1) 空間)で実行されます。

応用

  • ファイルシステム: 2つのファイルの共通親ディレクトリの検索
  • バージョン管理: Git の merge-base はコミットグラフで2つのコミットの LCA を見つける
  • ネットワーキング: 2つのネットワークノード間の共通ルーターの検索
  • 分類法: 2つのアイテムの最も具体的な共通カテゴリの検索

ユースケース

LCA は面接の定番問題(LeetCode #236、#235)であり、Git(2つのブランチのマージベースの検索)、ネットワークルーティング(ルーティングツリーの共通祖先)、DOM 操作(2つの HTML 要素の共通親の検索)などのシステムに現れます。木のノード間の距離を計算するための構成要素でもあります。

試してみる — Binary Tree Visualizer

フルツールを開く