Skip to content

Commit f5fc191

Browse files
committed
[Gold II] Title: 트리의 높이와 너비, Time: 24 ms, Memory: 69908 KB -BaekjoonHub
1 parent 2560668 commit f5fc191

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# [Gold II] 트리의 높이와 너비 - 2250
2+
3+
[문제 링크](https://www.acmicpc.net/problem/2250)
4+
5+
### 성능 요약
6+
7+
메모리: 69908 KB, 시간: 24 ms
8+
9+
### 분류
10+
11+
그래프 이론, 그래프 탐색, 트리, 깊이 우선 탐색
12+
13+
### 제출 일자
14+
15+
2025년 10월 20일 15:26:45
16+
17+
### 문제 설명
18+
19+
<p>이진트리를 다음의 규칙에 따라 행과 열에 번호가 붙어있는 격자 모양의 틀 속에 그리려고 한다. 이때 다음의 규칙에 따라 그리려고 한다.</p>
20+
21+
<ol>
22+
<li>이진트리에서 같은 레벨(level)에 있는 노드는 같은 행에 위치한다.</li>
23+
<li>한 열에는 한 노드만 존재한다.</li>
24+
<li>임의의 노드의 왼쪽 부트리(left subtree)에 있는 노드들은 해당 노드보다 왼쪽의 열에 위치하고, 오른쪽 부트리(right subtree)에 있는 노드들은 해당 노드보다 오른쪽의 열에 위치한다.</li>
25+
<li>노드가 배치된 가장 왼쪽 열과 오른쪽 열 사이엔 아무 노드도 없이 비어있는 열은 없다.</li>
26+
</ol>
27+
28+
<p>이와 같은 규칙에 따라 이진트리를 그릴 때 각 레벨의 너비는 그 레벨에 할당된 노드 중 가장 오른쪽에 위치한 노드의 열 번호에서 가장 왼쪽에 위치한 노드의 열 번호를 뺀 값 더하기 1로 정의한다. 트리의 레벨은 가장 위쪽에 있는 루트 노드가 1이고 아래로 1씩 증가한다.</p>
29+
30+
<p>아래 그림은 어떤 이진트리를 위의 규칙에 따라 그려 본 것이다. 첫 번째 레벨의 너비는 1, 두 번째 레벨의 너비는 13, 3번째, 4번째 레벨의 너비는 각각 18이고, 5번째 레벨의 너비는 13이며, 그리고 6번째 레벨의 너비는 12이다.</p>
31+
32+
<p style="text-align: center;"><img alt="" src="https://upload.acmicpc.net/4e4aaa17-dc1d-4af9-a36a-3144259fb7d2/-/preview/" style="width: 488px; height: 176px;"></p>
33+
34+
<p>우리는 주어진 이진트리를 위의 규칙에 따라 그릴 때에 너비가 가장 넓은 레벨과 그 레벨의 너비를 계산하려고 한다. 위의 그림의 예에서 너비가 가장 넓은 레벨은 3번째와 4번째로 그 너비는 18이다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때는 번호가 작은 레벨을 답으로 한다. 그러므로 이 예에 대한 답은 레벨은 3이고, 너비는 18이다.</p>
35+
36+
<p>임의의 이진트리가 입력으로 주어질 때 너비가 가장 넓은 레벨과 그 레벨의 너비를 출력하는 프로그램을 작성하시오</p>
37+
38+
### 입력
39+
40+
<p>첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다. 노드들의 번호는 1부터 N까지이며, 자식이 없는 경우에는 자식 노드의 번호에 -1이 주어진다.</p>
41+
42+
### 출력
43+
44+
<p>첫째 줄에 너비가 가장 넓은 레벨과 그 레벨의 너비를 순서대로 출력한다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때에는 번호가 작은 레벨을 출력한다.</p>
45+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
let n = Int(readLine()!)!
2+
var child = [Bool](repeating: false, count: n+1)
3+
var tree = (0...n).map { i in Node(v: i) }
4+
var levels = [Int](repeating: 0, count: n)
5+
var maxColLevel = [Int:Int]()
6+
var minColLevel = [Int:Int]()
7+
8+
for _ in 0..<n {
9+
let glr = readLine()!.split { $0 == " " }.map { Int(String($0))! },
10+
g = glr[0],
11+
l = glr[1],
12+
r = glr[2]
13+
if l != -1 {
14+
tree[g].left = l
15+
child[l] = true
16+
}
17+
if r != -1 {
18+
tree[g].right = r
19+
child[r] = true
20+
}
21+
}
22+
23+
let rootNode = (1...n).filter { child[$0] == false }.first!
24+
25+
var colPos = -1
26+
27+
dfs(rootNode, 1)
28+
29+
var level = 0
30+
var width = 0
31+
32+
for key in maxColLevel.keys {
33+
let levelWidth = maxColLevel[key]! - minColLevel[key]! + 1
34+
if levelWidth == width, level > key {
35+
level = key
36+
width = levelWidth
37+
continue
38+
}
39+
if levelWidth > width {
40+
level = key
41+
width = levelWidth
42+
}
43+
}
44+
45+
print(level, width)
46+
47+
// 깊이우선탐색으로 레벨별 너비를 구한다.
48+
func dfs(_ current: Int, _ level: Int) {
49+
if let left = tree[current].left {
50+
dfs(left, level + 1)
51+
}
52+
53+
colPos += 1
54+
levels[colPos] = level
55+
56+
maxColLevel[level, default: Int.min] = colPos > maxColLevel[level, default: Int.min] ? colPos : maxColLevel[level, default: Int.min]
57+
minColLevel[level, default: Int.max] = colPos < minColLevel[level, default: Int.max] ? colPos : minColLevel[level, default: Int.max]
58+
59+
if let right = tree[current].right {
60+
dfs(right, level + 1)
61+
}
62+
}
63+
64+
class Node {
65+
init(v: Int, left: Int? = nil, right: Int? = nil) {
66+
self.v = v
67+
self.left = left
68+
self.right = right
69+
}
70+
let v: Int
71+
var left: Int?
72+
var right: Int?
73+
}

0 commit comments

Comments
 (0)