문제 설명
하나의 이진 트리(binary tree)가 주어졌을 때, 해당 트리의 최소 깊이(minimum depth)를 구하는 것이 이 글의 목표입니다. 여기서 최소 깊이란 루트 노드에서 가장 가까운 리프(leaf) 노드까지의 최단 경로에 포함된 노드의 개수를 의미합니다.
예를 들어, 아래와 같은 이진 트리가 입력으로 주어진다고 가정해 보겠습니다.

루트 노드(3)에서 가장 가까운 리프 노드는 9이므로, 이 경우 출력 결과는 2가 됩니다.
접근 방법: BFS(너비 우선 탐색)
이 문제는 레벨 순회(level-order traversal), 즉 BFS 방식으로 효율적으로 해결할 수 있습니다. 트리를 위에서부터 한 층씩 내려가며 탐색하다가 처음으로 리프 노드를 만나는 순간의 레벨이 곧 최소 깊이이기 때문입니다. 구체적인 알고리즘 단계는 다음과 같습니다.
- 트리 노드를 저장할 배열
aa를 정의하고, 그 끝에 루트 노드를 삽입합니다. - 다음 레벨의 노드를 저장할 또 다른 배열
ak를 정의하고,level = 0으로 초기화합니다. - 루트가
null이라면 즉시 0을 반환합니다. aa의 크기가 0이 아닌 동안 아래 과정을 반복합니다.ak를 비우고level을 1 증가시킵니다.aa에 있는 모든 노드a에 대해 검사합니다.a의 왼쪽 자식과 오른쪽 자식이 모두 존재하지 않으면, 현재level값을 반환하고 반복문을 빠져나옵니다.- 왼쪽 자식이 존재하면
ak의 끝에 추가합니다. - 오른쪽 자식이 존재하면
ak의 끝에 추가합니다.
aa = ak로 갱신하여 다음 레벨로 이동합니다.
- 반복이 모두 끝나면 0을 반환합니다.
C++ 구현 예제
아래의 전체 구현 코드를 통해 동작 방식을 더 명확하게 이해할 수 있습니다.
#include <bits/stdc++.h>
using namespace std;
class TreeNode{
public:
int val;
TreeNode *left, *right;
TreeNode(int data){
val = data;
left = NULL;
right = NULL;
}
};
void insert(TreeNode **root, int val){
queue<TreeNode*> q;
q.push(*root);
while(q.size()){
TreeNode *temp = q.front();
q.pop();
if(!temp->left){
if(val != NULL)
temp->left = new TreeNode(val);
else
temp->left = new TreeNode(0);
return;
}
else{
q.push(temp->left);
}
if(!temp->right){
if(val != NULL)
temp->right = new TreeNode(val);
else
temp->right = new TreeNode(0);
return;
}
else{
q.push(temp->right);
}
}
}
TreeNode *make_tree(vector<int> v){
TreeNode *root = new TreeNode(v[0]);
for(int i = 1; i<v.size(); i++){
insert(&root, v[i]);
}
return root;
}
class Solution {
public:
int minDepth(TreeNode* root) {
vector<TreeNode*> aa;
aa.push_back(root);
vector<TreeNode*> ak;
int level = 0;
if (root == NULL || root->val == 0) {
return 0;
}
while (aa.size() != 0) {
ak.clear();
level++;
for (TreeNode* a : aa) {
if ((a->left == NULL || a->left->val == 0) && (a->right == NULL || a->right->val == 0)) {
return level;
break;
}
if (a->left != NULL) {
ak.push_back(a->left);
}
if (a->right != NULL) {
ak.push_back(a->right);
}
}
aa = ak;
}
return 0;
}
};
main(){
Solution ob;
vector<int> v = {3,9,20,NULL,NULL,15,7};
TreeNode *root = make_tree(v);
cout << (ob.minDepth(root));
}
실행 결과 확인
입력
{3,9,20,NULL,NULL,15,7}
출력
2
동작 원리와 성능 분석
위 예제에서 트리는 {3,9,20,NULL,NULL,15,7}로 구성됩니다. 루트 3의 왼쪽 자식인 9는 리프 노드이므로, 첫 번째 레벨 검사에서 바로 최소 깊이 2가 반환됩니다. 만약 DFS(깊이 우선 탐색)를 사용했다면 전체 경로를 끝까지 확인한 후 최솟값을 비교해야 하지만, BFS는 가장 얕은 리프 노드를 먼저 발견하는 즉시 탐색을 종료할 수 있어 이 문제에 특히 적합합니다.
- 시간 복잡도: O(N) — 최악의 경우 트리의 모든 노드를 한 번씩 방문합니다.
- 공간 복잡도: O(N) — 레벨별 노드를 저장하는 큐(배열) 공간이 필요합니다.
이처럼 BFS 기반 레벨 순회를 활용하면 이진 트리의 최소 깊이를 간결하고 효율적으로 계산할 수 있습니다.