[c++] 가장 가까운 공통 조상(Lowest Common Ancestor)

가장 가까운 공통 조상(Lowest Common Ancestor, LCA)은 이진 트리에서 두 노드의 가장 가까운 공통 조상을 찾는 알고리즘입니다.

Algorithm

  1. Depth-First Search (DFS) : 루트부터 잎 노드까지 이동하며 노드의 부모 정보와 각 노드의 깊이를 저장합니다.
  2. Sparse Table : 이진 트리에서 LCA를 빠르게 찾기 위해 희소 테이블을 만듭니다.
  3. LCA Query : 희소 테이블을 사용하여 두 노드의 가장 가까운 공통 조상을 찾습니다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 10005;
const int LOGN = 15; // log2(MAXN)

int n, timer;
vector<int> adj[MAXN]; // adjacency list
int parent[MAXN][LOGN]; // parent[i][j]는 i의 2^j번째 조상을 나타냄
int depth[MAXN]; // 각 노드의 깊이

void dfs(int v, int par, int d) {
    depth[v] = d;
    parent[v][0] = par;
    for (int i = 0; i < adj[v].size(); i++) {
        int u = adj[v][i];
        if (u != par)
            dfs(u, v, d+1);
    }
}

void buildSparseTable() {
    for (int j = 1; j < LOGN; j++) {
        for (int i = 1; i <= n; i++) {
            if (parent[i][j-1] != -1)
                parent[i][j] = parent[parent[i][j-1]][j-1];
        }
    }
}

int lca(int u, int v) {
    if (depth[u] < depth[v])
        swap(u, v);

    int diff = depth[u] - depth[v];
    for (int i = 0; i < LOGN; i++) {
        if (diff & (1 << i))
            u = parent[u][i];
    }

    if (u == v)
        return u;

    for (int i = LOGN - 1; i >= 0; i--) {
        if (parent[u][i] != parent[v][i]) {
            u = parent[u][i];
            v = parent[v][i];
        }
    }
    
    return parent[u][0];
}

시간 복잡도 및 공간 복잡도

이 알고리즘은 효율적으로 LCA를 찾을 수 있는데, 트리의 노드 수(N)에 대해 O(NlogN)의 공간과 시간 복잡도가 소요됩니다.

결론

가장 가까운 공통 조상 알고리즘은 이진 트리에서 두 노드의 LCA를 효율적으로 찾는 알고리즘입니다. 이를 위해 DFS와 희소 테이블을 사용하여 쿼리 시간을 최적화하고, O(logN) 시간 안에 LCA를 찾을 수 있습니다.

더 자세한 내용은 다음을 참고하세요.