# Problem
이진트리를 다음의 규칙에 따라 행과 열에 번호가 붙어있는 격자 모양의 틀 속에 그리려고 한다. 이때 다음의 규칙에 따라 그리려고 한다.
이와 같은 규칙에 따라 이진트리를 그릴 때 각 레벨의 너비는 그 레벨에 할당된 노드 중 가장 오른쪽에 위치한 노드의 열 번호에서 가장 왼쪽에 위치한 노드의 열 번호를 뺀 값 더하기 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이 주어진다. 출력첫째 줄에 너비가 가장 넓은 레벨과 그 레벨의 너비를 순서대로 출력한다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때에는 번호가 작은 레벨을 출력한다. |
# Solution 1
class Node:
def __init__(self, number, left_node, right_node):
self.parent = -1
self.number = number
self.left_node = left_node
self.right_node = right_node
def in_order(node, level):
global level_depth, x
level_depth = max(level_depth, level)
if node.left_node != -1:
in_order(tree[node.left_node], level + 1)
level_min[level] = min(level_min[level], x)
level_max[level] = max(level_max[level], x)
x += 1
if node.right_node != -1:
in_order(tree[node.right_node], level + 1)
n = int(input())
tree = {}
level_min = [n]
level_max = [0]
root = -1
x = 1
level_depth = 1
# 1
for i in range(1, n + 1):
tree[i] = Node(i, -1, -1)
level_min.append(n)
level_max.append(0)
# 2
for _ in range(n):
number, left_node, right_node = map(int, input().split())
tree[number].left_node = left_node
tree[number].right_node = right_node
if left_node != -1:
tree[left_node].parent = number
if right_node != -1:
tree[right_node].parent = number
# 3
for i in range(1, n + 1):
if tree[i].parent == -1:
root = i
# 4
in_order(tree[root], 1)
# 5
result_level = 1
result_width = level_max[1] - level_min[1] + 1
for i in range(2, level_depth + 1):
width = level_max[i] - level_min[i] + 1
if result_width < width:
result_level = i
result_width = width
print(result_level, result_width)
중위 순회(왼쪽 노드 - 루트 - 오른쪽 노드) 순서로 각 레벨마다 최소값과 최대값의 인덱스를 저장
노드가 존재하면 계속 반복 호출하므로 자동으로 가장 왼쪽의 노드부터 인덱스가 부여된다.
변수 x (현재 노드의 인덱스)와 저장되어있는 최소/최대 인덱스 비교하여 업데이트
1. 각 노드 생성 ( 데이터 값만 있는)
- 가능한 최대 레벨의 깊이는 노드의 개수이다 ( 한쪽으로만 계속 연결될 경우) -> level_min과 level_max를 노드 수만큼 초기화 한다.
- 나중에 level_depth 사용해서 사용한 레벨 계산
2. input 받으면서 parent, left,right 노드 저장
3. root 노드가 어떤건지 모름 -> 들어오는 노드마다 parent 저장해서 parent가 없는 노드가 루트 노드
4. 루트 노트를 찾은 후 중위 순회로 각 레벨의 인덱스의 최소 값과 최대 값 찾기
5. 각 레벨(level_depth까지)마다 최대값과 최소값의 인덱스 차이로 너비 계산 후 너비의 최대값 출력
'Algorithm > 백준 알고리즘 풀이' 카테고리의 다른 글
[Baekjoon] 1715. 카드 정렬하기 (0) | 2021.04.20 |
---|---|
[Baekjoon] 1927. 최소 힙 (0) | 2021.04.20 |
[Baekjoon] 1991. 트리 순회 (0) | 2021.04.20 |
❗️[Baekjoon] 1939. 중량제한 ( 이진 탐색 ) (0) | 2021.04.19 |
❗️[Baekjoon] 2110. 공유기 설치 ( 이진 탐색 ) (0) | 2021.04.19 |