티스토리 뷰
문제
이진트리를 다음의 규칙에 따라 행과 열에 번호가 붙어있는 격자 모양의 틀 속에 그리려고 한다. 이때 다음의 규칙에 따라 그리려고 한다.
- 이진트리에서 같은 레벨(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이 주어진다.
출력
첫째 줄에 너비가 가장 넓은 레벨과 그 레벨의 너비를 순서대로 출력한다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때에는 번호가 작은 레벨을 출력한다.
힌트 1
- 중위 순회는 X축을 기준으로 왼쪽부터 방문한다는 특징이 있다.
- 그러므로 너비를 구하려면 중위순회를 이용하면 된다.
- 중위 순회를 이용하되, 추가적으로 Level 값을 저장하도록 하여 문제를 해결할 수 있다.
루트 찾기
- 루트가 1이라고 문제에 없기 때문에 루트를 찾아줘야 함
- Node Class에 parent의 여부를 가지고 있어서 parent가 없는 노드가 root node
실수
- 같은 레벨인 값을 List로 가지고 있다가 정렬 후 첫 번째 원소와 마지막 원소를 통해서 너비를 구했다.
- 92%에서 실패를 하는걸보니 반례가 있었나보다.
- minLevel, maxLevel 배열을 통해서 구해줬더니 통과했다!
Map<Level, List<Count>> 코드는 이 코드를 짠 시간이 아쉬워서 주석처리만 했다.
import java.util.*;
import java.io.*;
public class Main {
static Map<Integer, Node> map;
static int count = 0;
static int level = 0;
static int[] levelMin;
static int[] levelMax;
// static Map<Integer, List<Integer>> levelMap;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.valueOf(st.nextToken());
map = new HashMap<>();
// levelMap = new HashMap<>();
levelMin = new int[N+1];
levelMax = new int[N+1];
for(int i = 1 ;i<=N;i++) {
st = new StringTokenizer(br.readLine());
int root = Integer.valueOf(st.nextToken());
int left = Integer.valueOf(st.nextToken());
int right = Integer.valueOf(st.nextToken());
map.put(root, new Node(root, left, right));
levelMin[i] = N;
}
// 루트 구하기
int root = getRoot(map);
inOrder(map.get(root));
int maxWidthLevel = 1;
int maxWidth = levelMax[1] - levelMin[1] + 1;
for(int i = 2;i<=N;i++) {
int width = levelMax[i] - levelMin[i] + 1;
if(maxWidth < width) {
maxWidthLevel = i;
maxWidth = width;
}
// for(Map.Entry<Integer, List<Integer>> entry : levelMap.entrySet()) {
// int key = entry.getKey();
// List<Integer> values = entry.getValue();
// if(values.size() == 1) continue;
// Collections.sort(values);
// int width = values.get(values.size()-1) - values.get(0) + 1;
// if(width > maxWidth) {
// maxWidthLevel = key;
// maxWidth = width;
// } else if(width == maxWidth) {
// if(key < maxWidthLevel) {
// maxWidthLevel = key;
// maxWidth = width;
// }
// }
}
System.out.println(maxWidthLevel + " " + maxWidth);
}
private static int getRoot(Map<Integer, Node> map) {
for(Map.Entry<Integer, Node> entry : map.entrySet()) {
Node node = entry.getValue();
if(node.left != -1) {
map.get(node.left).parent = true;
}
if(node.right != -1) {
map.get(node.right).parent = true;
}
}
for(Map.Entry<Integer, Node> entry : map.entrySet()) {
Node node = entry.getValue();
if(!node.parent) return entry.getKey();
}
return 0;
}
private static void inOrder(Node node) {
level++;
if (node.left != -1) {
inOrder(map.get(node.left));
}
// System.out.println("root : " + node.root + " level : " + level + " count : " + count);
// if(!levelMap.containsKey(level)) {
// levelMap.put(level, new ArrayList<>());
// }
levelMin[level] = Math.min(levelMin[level], count);
levelMax[level] = count++;
//levelMap.get(level).add(count++);
level--;
if (node.right != -1) {
level++;
inOrder(map.get(node.right));
level--;
}
}
static class Node {
boolean parent;
int root;
int left;
int right;
Node(int root, int left, int right) {
this.parent = false;
this.root = root;
this.left = left;
this.right = right;
}
}
}
'알고리즘' 카테고리의 다른 글
BOJ1927 최소 힙 java (0) | 2022.01.21 |
---|---|
BOJ1991 트리 순회 java (0) | 2022.01.19 |
BOJ1939 중량제한 java (0) | 2022.01.17 |
BOJ2110 공유기 설치 java (0) | 2022.01.16 |
BOJ1976 여행 가자 java - 분리 집합 [2] (0) | 2022.01.14 |
- Total
- Today
- Yesterday
- 클린 아키텍처
- 이펙티브 자바
- MSA
- JPA
- 객체지향
- 정규표현식
- Kotlin
- 테라폼
- 알고리즘
- 디자인패턴
- kkoon9
- Olympiad
- 프로그래머스
- 이팩티브 자바
- Algorithm
- Spring Boot
- C++
- AWS
- Java
- programmers
- 디자인 패턴
- Spring
- 코테
- Effective Java
- node.js
- 백준
- BOJ
- kotest
- BAEKJOON
- 클린 코드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |