사이클이 없는 연결 그래프가 트리다. 정점이 V개이면 간선은 정확히 V-1개다. 간선 하나를 더 추가하면 사이클이 생기고, 하나를 제거하면 연결이 끊긴다.
회사 조직도를 떠올리면 이해하기 쉽다. 대표가 루트, 각 팀장이 자식, 팀원이 리프 노드다. 한 팀원이 두 팀장에 동시에 속하는 일은 없다. 그런 경우가 생기면 그것은 이미 트리가 아니다.
1
/ \
2 3
/ \ \
4 5 6
|
7
용어 정리
용어
설명
루트(Root)
부모가 없는 최상단 노드
부모(Parent)
자신보다 한 단계 위 노드
자식(Child)
자신보다 한 단계 아래 노드
리프(Leaf)
자식이 없는 노드
깊이(Depth)
루트로부터의 거리 (루트 = 0)
높이(Height)
리프까지의 최대 거리
코딩테스트에서의 입력 형태
코딩테스트에서 트리는 보통 간선 목록으로 주어진다. defaultdict(list)로 인접 리스트를 구성하고 양방향으로 연결하는 것이 기본 패턴이다.
import sys
from collections importdefaultdictdefbuild_adjacency(n, edges):
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
return graph
재귀 깊이가 10만 이상이면 RecursionError가 발생한다. sys.setrecursionlimit으로 한도를 올리거나, 스택으로 순회를 직접 구현한다.
import sys
sys.setrecursionlimit(200000)
defpreorder_iterative(root):
if root isNone:
return []
result = []
stack = [root]
while stack:
node = stack.pop()
result.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return result
print("반복 전위:", preorder_iterative(root))
출력:
반복 전위: [1, 2, 4, 5, 3]
중위 순회는 이진 탐색 트리(BST)에서 오름차순 정렬 결과를 낸다는 특성이 있어, BST 검증 문제에서 자주 활용된다.
3. LCA (최소 공통 조상)
정의
LCA(Lowest Common Ancestor)는 두 노드의 조상 중 가장 깊은 공통 정점이다.
1
/ \
2 3
/ \
4 5
4와 5의 LCA = 2 (두 노드 모두 2의 자식)
4와 3의 LCA = 1 (2와 3의 공통 조상은 1뿐)
전처리: parent와 depth 배열 구성
루트에서 BFS를 돌며 각 노드의 부모와 깊이를 기록한다.
from collections importdeque, defaultdictdefbuild_tree(n, edges, root):
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
parent = [0] * (n + 1)
depth = [0] * (n + 1)
visited = [False] * (n + 1)
q = deque([root])
visited[root] = Truewhile q:
node = q.popleft()
for neighbor in graph[node]:
ifnot visited[neighbor]:
visited[neighbor] = True
parent[neighbor] = node
depth[neighbor] = depth[node] + 1
q.append(neighbor)
return parent, depth
Naive LCA
두 노드의 깊이를 같은 수준으로 맞춘 뒤, 같은 노드에 도달할 때까지 동시에 부모 방향으로 올라간다.
deffind_lca(parent, depth, u, v):
while depth[u] > depth[v]:
u = parent[u]
while depth[v] > depth[u]:
v = parent[v]
while u != v:
u = parent[u]
v = parent[v]
return u