작성자: 조광형
작성일: 2024년 11월 26일
소개
본 강좌에서는 C# 프로그래밍 언어를 사용하여 ‘최소 공통 조상(LCA; Lowest Common Ancestor)’ 문제를 해결하는 방법에 대해 다룰 것입니다.
최소 공통 조상은 이진 트리에서 두 노드의 공통 조상 중 가장 깊은 노드를 의미합니다.
특정 알고리즘 및 자료 구조를 활용하여 이 문제를 해결하는 과정을 자세히 설명하겠습니다.
문제 설명
주어진 이진 트리와 두 개의 노드 A, B에 대해, A와 B의 최소 공통 조상을 찾는 문제입니다.
이진 트리는 비어있지 않으며, 모든 노드는 고유한 값을 갖습니다.
추가적으로 노드 A와 B는 반드시 트리에 존재한다고 가정합니다.
입력 형식
- 첫 번째 줄: 트리의 노드 수 N (1 ≤ N ≤ 10^5) - 두 번째 줄: N개의 공백으로 구분된 정수로 트리의 노드 값 - 세 번째 줄: 두 개의 정수 A, B (A, B는 트리의 노드에 존재)
출력 형식
- A와 B의 최소 공통 조상의 값
문제 예시
입력: 7 3 5 1 6 2 0 8 5 1 출력: 3
해결 방법
최소 공통 조상을 찾기 위한 여러 방법이 있지만, 일반적으로 트리의 깊이를 고려하면서
DFS(Depth First Search) 방식으로 탐색하는 방법이 효과적입니다.
이진 탐색 트리(BST)의 경우에는 A와 B가 각각 어느 서브트리에 속하는지를 판단하여
조상을 효율적으로 찾는 방법이 가능합니다. 하지만 일반적인 이진 트리에서는 부모 노드의 정보를 활용하는
방식이 필요합니다.
알고리즘 설계
알고리즘의 주요 단계는 다음과 같습니다.
- 입력으로 주어진 트리를 생성합니다.
- 각 노드에 대한 부모 노드를 맵 또는 배열로 저장합니다.
- 노드 A에서 루트까지의 경로를 기록합니다.
- 노드 B에서 루트까지의 경로를 기록합니다.
- 두 경로에서 첫 번째 공통 노드를 찾습니다.
C# 코드 구현
아래는 위의 알고리즘을 C#으로 구현한 코드입니다.
using System;
using System.Collections.Generic;
class TreeNode {
public int Value;
public TreeNode Left, Right;
public TreeNode(int value) {
this.Value = value;
this.Left = null;
this.Right = null;
}
}
class Program {
static Dictionary nodeMap = new Dictionary();
static TreeNode root;
public static void Main(string[] args) {
int N = Convert.ToInt32(Console.ReadLine());
int[] values = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
int A = Convert.ToInt32(Console.ReadLine());
int B = Convert.ToInt32(Console.ReadLine());
BuildTree(values, 0, N);
TreeNode ancestor = FindLCA(root, A, B);
Console.WriteLine(ancestor.Value);
}
static TreeNode BuildTree(int[] values, int index, int N) {
if (index < N) {
TreeNode node = new TreeNode(values[index]);
nodeMap[values[index]] = node;
node.Left = BuildTree(values, 2 * index + 1, N);
node.Right = BuildTree(values, 2 * index + 2, N);
return node;
}
return null;
}
static TreeNode FindLCA(TreeNode node, int A, int B) {
if (node == null) return null;
if (node.Value == A || node.Value == B) return node;
TreeNode leftLCA = FindLCA(node.Left, A, B);
TreeNode rightLCA = FindLCA(node.Right, A, B);
if (leftLCA != null && rightLCA != null) return node;
return (leftLCA != null) ? leftLCA : rightLCA;
}
}
코드 설명
1. TreeNode 클래스: 이진 트리의 노드를 표현합니다. 각각의 노드는 값과 왼쪽, 오른쪽 자식을 갖습니다.
2. Main 메서드: 프로그램의 시작점입니다. 사용자로부터 입력을 받고 트리를 생성한 후 LCA를 찾습니다.
3. BuildTree 메서드: 배열을 사용하여 이진 트리를 구축합니다. 재귀적으로 호출되어 트리를 구성합니다.
4. FindLCA 메서드: 재귀적으로 트리를 탐색하며 두 노드 A와 B의 최소 공통 조상을 찾습니다.
시간 복잡도
본 알고리즘의 시간 복잡도는 O(N)입니다.
트리를 한 번 순회하면서 각 노드를 방문하므로 노드 수에 비례하여 증가합니다.
공간 복잡도 또한 O(N)인데, 이는 재귀 호출 스택과 노드 정보를 저장하는 데 사용되는 공간 때문입니다.
맺음말
이번 강좌에서는 C#을 이용하여 최소 공통 조상 문제를 해결하는 방법에 대해 배웠습니다.
알고리즘의 원리를 이해하고 코드를 구현하면서, 코딩 테스트에서 이와 같은 트리 문제를 효과적으로 해결하는
방법에 대한 감을 잡을 수 있었을 것입니다.
다음 시간에는 다른 데이터 구조나 알고리즘 문제를 깊이 있게 다뤄보도록 하겠습니다.
감사합니다.