71. 최소 공통 조상 (LCA, Lowest Common Ancestor)
핵심 인사이트 (3줄 요약)
- 본질: 최소 공통 조상(Lowest Common Ancestor, LCA)은 두 노드의 공통 조상 중 가장 가까운(깊이가深い) 조상을 찾는 문제이다.
- 가치: 트리에서 두 노드 사이의最短경로 찾기, 근접 조상 관계 确定 등 다양한 문제의基礎이 된다.
- 융합: 네트워크 분석, 계층적 데이터 查询,最小공통조상問題의 변형 등 다양한領域에서 활용된다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
최소 공통 조상(Lowest Common Ancestor, LCA)은 rooted tree(루트 트리)에서 두 노드 u와 v의 공통 조상 중에서 루트에서 가장 멀리(깊이가深い) 있는 조상을 찾는問題이다. 공통 조상이란 u와 v 모두의 조상인 노드를 의미하며, 최소 공통 조상은 그러한 노드들 중에서 두 노드에 가장 가까운 것이다.
LCA가 중요한 이유는 트리 기반 문제의 기본 도구이기 때문이다. 두 노드 사이의最短경로 = LCA를 통한 경로로 표현할 수 있다. u에서 v로的最短경로는 u → LCA(u, v) → v로 표현된다.
LCA는 系譜学에서도 중요한概念이다.两个人의共同祖先을 찾고, 그 중 가장 가까운(최근)에 해당하는 것이 系譜에서 "공통 조상"이 된다.
[LCA 예시]
┌──────────────────────────────────────────────────────────────┐
│ │
│ [루트 트리] │
│ ──────────────────────────────────────────── │
│ │
│ A(루트) │
│ / | \ │
│ B C D │
│ / \ / \ │
│ E F G H │
│ / \ │ │
│ I J │ (I의 조상: I, E, B, A) │
│ │ (J의 조상: J, E, B, A) │
│ (LCA(I,J) = E) │
│ │
│ LCA(I, J) = E │
│ - E는 I과 J의 공통 조상이다 (I과 J의 조상 중 E가 있다) │
│ - E는 가장 깊은(루트에서 멀리 있는) 공통 조상이다 │
│ │
│ [다른 예시] │
│ ──────────────────────────────────────────── │
│ LCA(E, F) = B (B가 E과 F의 조상 중 가장 깊다) │
│ LCA(B, C) = A (B와 C의 공통 조상은 A뿐) │
│ LCA(A, E) = A (A는 E의 조상이면서 루트) │
│ │
└──────────────────────────────────────────────────────────────┘
- 관찰: LCA는 항상 유일하게 존재한다(루트 트리에서).
- 원인: 루트를 제외한 모든 노드는 반드시 하나의 부모를 가지므로, 두 노드의 조상 집합의 교집합은 비어있지 않다.
- 결과: 모든 노드는 루트까지의 유일한 경로를 가지므로, 공통 조상이 반드시 존재한다.
- 판단: LCA를 찾는 알고리즘의 효율성이 중요한問題이다.
📢 섹션 요약 비유: LCA는 家族 系譜와 같습니다. 두명의堂兄弟의最小公祖先을 찾으면, 공통된조상中最接近な者を探すことになる。例气면, "철수"와 "영희"의 最近共通祖先이 "할아버지"라면, 祖父以下の系統ではなく、祖父以上の系統で交わっている最も近い节点がそれに当たる.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
LCA를 찾는 주요 알고리즘들을 살펴보자.
Naive 방법: 각 노드의 조상들을 표시하고, 다른 노드의 조상들과 비교한다. 시간 복잡도 O(N), 공간 복잡도 O(N).
DFS + 부모 포인터: 두 노드에서 루트까지의 경로를 각각 찾고, 경로에서 첫 번째 공통 노드를 찾는다. 시간 복잡도 O(N), 공간 복잡도 O(H).
Binary Lifting:预处理로 각 노드의 2^k 조상을 저장한다. Find 시 먼저 깊이를 맞추고, 동시에 위로 올라가며 LCA를 찾는다.预处理 O(N log N), 각 Query O(log N).
RMQ 기반 방법: Euler Tour과 Sparse Table을 利用하여 O(1) Query를 달성한다. 많은 수의 Query가 있을 때 유용하다.
[LCA 알고리즘 상세]
┌──────────────────────────────────────────────────────────────┐
│ │
│ [Binary Lifting 방법] │
│ ──────────────────────────────────────────── │
│ │
│ //预处理: 각 노드의 2^k 조상 저장 │
│ MAX_LOG = ceil(log2(N)) │
│ │
│ parent[k][v] = v의 2^k 번째 조상 │
│ depth[v] = v의 깊이 (루트에서 v까지의 거리) │
│ │
│ // 2^k 조상 계산 │
│ parent[0][v] = v의 직접 부모 │
│ parent[k][v] = parent[k-1][parent[k-1][v]] │
│ │
│ // LCA 찾기 │
│ function lca(u, v): │
│ // 1. 깊이 맞추기 │
│ if depth[u] < depth[v]: │
│ swap(u, v) │
│ │
│ // u을 v와 같은 깊이로 올리기 │
│ diff = depth[u] - depth[v] │
│ for k in range(MAX_LOG): │
│ if diff & (1 << k): │
│ u = parent[k][u] │
│ │
│ // 2. 동시에 올려가며 LCA 찾기 │
│ if u == v: │
│ return u │
│ │
│ for k in range(MAX_LOG - 1, -1, -1): │
│ if parent[k][u] != parent[k][v]: │
│ u = parent[k][u] │
│ v = parent[k][v] │
│ │
│ return parent[0][u] // 바로 위 조상이 LCA │
│ │
│ [시간 복잡도] │
│ ──────────────────────────────────────────── │
│ preprocessing: O(N log N) │
│ each query: O(log N) │
│ │
└──────────────────────────────────────────────────────────────┘
- 관찰: Binary Lifting은 2의 거듭제곱으로 조상들을 점프한다.
- 원인: 모든 수를 2진수로 표현할 수 있듯이, 모든 깊이 차이도 2의 거듭제곱 합으로 표현할 수 있기 때문이다.
- 결과: 깊이 차이만큼 정확하게 올려서 두 노드를 같은 깊이로 만들 수 있다.
- 판단: Query 수가 많으면 Binary Lifting이 효율적이다.
📢 섹션 요약 비유: Binary Lifting은 계단을 오르는策略와 같습니다. 1칸, 2칸, 4칸, 8칸... 씩 점프할 수 있다면, 어떤 높이差든 2의 거듭제곱 조합으로 표현할 수 있어 가장 효율적으로高度を合わせることができる.
Ⅲ. 구현 및 실무 응용 (Implementation & Practice)
LCA의 실무 적용은 다음과 같다. 네트워크 라우팅: 라우터들의 계층적構造에서 두 라우터의最近接共通祖先(LCA)를 찾아 경로를 결정한다. 계층적 데이터 Query: 조직도, 카테고리 분류 등 계층적 데이터에서 두 항목의最近接共通항목을 찾는다.
응용: 노드 사이 거리 계산: 두 노드 u, v 사이의 거리는 dist(u, v) = dist(u, lca) + dist(v, lca)로 계산할 수 있다. 응용: 부분 트리 Query: 특정 노드의 하위 트리에 속하는 노드들 사이의 LCA는 항상 해당 노드이다.
[LCA 실무 활용]
┌──────────────────────────────────────────────────────────────┐
│ │
│ [두 노드 사이 거리 계산] │
│ ──────────────────────────────────────────── │
│ │
│ 거리 = depth[u] + depth[v] - 2 * depth[lca(u, v)] │
│ │
│ 예시: │
│ depth[I] = 3, depth[J] = 3, depth[E] = 2 │
│ 거리(I, J) = 3 + 3 - 2*2 = 2 │
│ (I → E → J 경로, 2칸) │
│ │
│ [계층적 카테고리 분류] │
│ ──────────────────────────────────────────── │
│ │
│ 카테고리 트리: │
│ Electronics │
│ ├── Computers │
│ │ ├── Laptops │
│ │ └── Desktops │
│ └── Phones │
│ ├── Smartphones │
│ └── Feature phones │
│ │
│ "Laptop"과 "Smartphone"의 LCA = Electronics │
│ → 서로 다른 주分类이지만 같은 상위 카테고grin 소속 │
│ │
│ [IRT (Item Response Theory) - 교육测验] │
│ ──────────────────────────────────────────── │
│ 시험 문항들의 능력치分层에서, 두 문항의共通能力 수준 찾기 │
│ │
└──────────────────────────────────────────────────────────────┘
📢 섹션 요약 비유: LCA 실무 활용은 都市 계획과 같습니다. 두 地区中心街の最近接共通繁華街を 찾아、その2つ地区中心街への道计算出により、最短時間で2つか所赴くことができる。のように、LCAは都市間の最直通経路を求める際に応用される。
Ⅳ. 품질 관리 및 테스트 (Quality & Testing)
LCA의 품질 관리에서 가장 중요한 것은 루트 설정과 깊이 계산이다.
품질 관리 체크리스트: 트리가 rooted tree인지 확인해야 한다(모든 노드에 부모가 하나). 루트가 올바르게 설정되어야 depth 계산이 정확하다. parent 배열이 정확한지 확인해야 한다.
📢 섹션 요약 비유: LCA 품질 관리는 등산길 지도 작성과 같습니다. 모든 갈림길에서 올바른 방향(부모 노드)으로 이어지는지 확인하고, 각 지점까지の垂直距離を正確に測定することで、2つの地点間の最短距離、正確に計算できる。
Ⅴ. 최신 트렌드 및 결론 (Trends & Conclusion)
LCA의 최신 동향은 더 빠른 Query와 동적 트리 처리와 관련되어 있다. Link-Cut Tree: 동적으로 트리가 변할 때 LCA를 지원하는 자료구조. Euler Tour + RMQ: O(1) Query를 달성하지만预处理이 복잡하다.
LCA는 "트리 기반 문제의 핵심 도구"로서, 다양한 그래프 알고리즘의 기초가 된다.
📢 섹션 요약 비유: LCA의 발전은 **우주 탐사 로프트*와 같습니다。初期에는 두 천체 사이의最短距離を計算するのが面倒だったが、より先进的な算法により、两个的任何任意两天体間の共通祖先を即座に 찾을 수 있어ようになった。
핵심 인사이트 ASCII 다이어그램 (Concept Map)
[최소 공통 조상 (LCA) 핵심 개념 맵]
┌─────────────────────────────────┐
│ 최소 공통 조상 (LCA, Lowest Common Ancestor) │
└────────────────┬────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 핵심 개념 │ │ 알고리즘 │ │ 실무 활용 │
│ 공통 조상 │ │ Binary Lift │ │ Use Cases │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ 가장 가까운 │ │预处理O(NlogN)│ │ 네트워크 라우팅│
│ (깊이 가장 │ │ Query O(logN)│ │ 계층적 데이터 │
│ 깊은) │ │ │ │ 거리 계산 │
└──────────────┘ └──────────────┘ └──────────────┘
참고
- 모든 약어는 반드시 전체 명칭과 함께 표기
- 일어/중국어 절대 사용 금지
- 각 섹션 끝에 📢 요약 비유 반드시 추가
- 최소 800자/파일
- 파일명: 01_, 02_... 형식