BOJ_2250_트리의 높이와 너비
[Gold II] 트리의 높이와 너비 - 2250
성능 요약
메모리: 23036 KB, 시간: 284 ms
분류
깊이 우선 탐색, 그래프 이론, 그래프 탐색, 트리
제출 일자
2024년 10월 29일 07:50:45
문제 설명
이진트리를 다음의 규칙에 따라 행과 열에 번호가 붙어있는 격자 모양의 틀 속에 그리려고 한다. 이때 다음의 규칙에 따라 그리려고 한다.
- 이진트리에서 같은 레벨(level)에 있는 노드는 같은 행에 위치한다.
- 한 열에는 한 노드만 존재한다.
- 임의의 노드의 왼쪽 부트리(left subtree)에 있는 노드들은 해당 노드보다 왼쪽의 열에 위치하고, 오른쪽 부트리(right subtree)에 있는 노드들은 해당 노드보다 오른쪽의 열에 위치한다.
- 노드가 배치된 가장 왼쪽 열과 오른쪽 열 사이엔 아무 노드도 없이 비어있는 열은 없다.
이와 같은 규칙에 따라 이진트리를 그릴 때 각 레벨의 너비는 그 레벨에 할당된 노드 중 가장 오른쪽에 위치한 노드의 열 번호에서 가장 왼쪽에 위치한 노드의 열 번호를 뺀 값 더하기 1로 정의한다. 트리의 레벨은 가장 위쪽에 있는 루트 노드가 1이고 아래로 1씩 증가한다.
아래 그림은 어떤 이진트리를 위의 규칙에 따라 그려 본 것이다. 첫 번째 레벨의 너비는 1, 두 번째 레벨의 너비는 13, 3번째, 4번째 레벨의 너비는 각각 18이고, 5번째 레벨의 너비는 13이며, 그리고 6번째 레벨의 너비는 12이다.
우리는 주어진 이진트리를 위의 규칙에 따라 그릴 때에 너비가 가장 넓은 레벨과 그 레벨의 너비를 계산하려고 한다. 위의 그림의 예에서 너비가 가장 넓은 레벨은 3번째와 4번째로 그 너비는 18이다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때는 번호가 작은 레벨을 답으로 한다. 그러므로 이 예에 대한 답은 레벨은 3이고, 너비는 18이다.
임의의 이진트리가 입력으로 주어질 때 너비가 가장 넓은 레벨과 그 레벨의 너비를 출력하는 프로그램을 작성하시오
입력
첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다. 노드들의 번호는 1부터 N까지이며, 자식이 없는 경우에는 자식 노드의 번호에 -1이 주어진다.
출력
첫째 줄에 너비가 가장 넓은 레벨과 그 레벨의 너비를 순서대로 출력한다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때에는 번호가 작은 레벨을 출력한다.
문제 풀이
트리의 행을 dfs로 찾아가며 부여하고 depth를 레벨로 생각하였다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* Author: nowalex322, Kim HyeonJae
*/
import java.io.*;
import java.util.*;
public class Main {
class Node{
int num;
int left, right;
public Node(int num, int left, int right) {
this.num = num;
this.left = left;
this.right = right;
}
}
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static Set<Integer> rootList = new HashSet<>();
static Map<Integer, Node> tree = new HashMap<Integer, Node>();
static Map<Integer, List<Integer>> levelColumn = new HashMap<>(); // 레벨별 열 list
static int columnCnt=0;
static int maxLevel=0, maxLength=0;
public static void main(String[] args) throws Exception {
new Main().solution();
}
public void solution() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
// br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
for(int i=1; i<=N; i++) {
rootList.add(i);
}
for(int i=1; i<=N; i++) {
st = new StringTokenizer(br.readLine());
int num = Integer.parseInt(st.nextToken());
int left = Integer.parseInt(st.nextToken());
int right = Integer.parseInt(st.nextToken());
tree.put(num, new Node(num, left, right));
if(left != -1) rootList.remove(left);
if(right != -1) rootList.remove(right);
}
int root = rootList.stream().findFirst().get();
dfs(root, 1);
for(Map.Entry<Integer, List<Integer>> entry : levelColumn.entrySet()){
int level = entry.getKey();
List<Integer> column = entry.getValue();
// 길이 = 마지막열 - 첫번째열 + 1
int len = column.get(column.size()-1) - column.get(0) + 1;
if(len > maxLength) {
maxLevel = level;
maxLength = len;
}
}
bw.write(maxLevel + " " + maxLength);
bw.flush();
bw.close();
br.close();
}
private void dfs(int num, int level) {
Node node = tree.get(num);
if(node.left != -1) {
dfs(node.left, level+1);
}
// 현재 노드의 열 번호 처리
columnCnt++;
levelColumn.computeIfAbsent(level, columnIdx -> new ArrayList<>()).add(columnCnt);
if(node.right != -1) {
dfs(node.right, level+1);
}
}
}