출처
https://www.acmicpc.net/problem/2250
문제
이진트리를 다음의 규칙에 따라 행과 열에 번호가 붙어있는 격자 모양의 틀 속에 그리려고 한다. 이때 다음의 규칙에 따라 그리려고 한다.
- 이진트리에서 같은 레벨(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이 주어진다.
출력
첫째 줄에 너비가 가장 넓은 레벨과 그 레벨의 너비를 순서대로 출력한다. 너비가 가장 넓은 레벨이 두 개 이상 있을 때에는 번호가 작은 레벨을 출력한다.
예제
입력 | 출력 |
19 1 2 3 2 4 5 3 6 7 4 8 -1 5 9 10 6 11 12 7 13 -1 8 -1 -1 9 14 15 10 -1 -1 11 16 -1 12 -1 -1 13 17 -1 14 -1 -1 15 18 -1 16 -1 -1 17 -1 19 18 -1 -1 19 -1 -1 |
3 18 |
풀이
중위순환
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class BOJ2250
{
static Node []tree;
static int n;
static int [] min;
static int [] max;
static int root;
static int indexNum;
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
tree=new Node[n+1]; //2차원 배열 할당하려면 1. 먼저 이렇게 하고
min=new int[n+1];
max=new int[n+1];
for(int i=0;i<n+1;i++)
{
tree[i]=new Node(); //2. tree[i]마다 한번씩 더 할당해줘야함
min[i]=n;
max[i]=1;
}
// n+1인 경우 입력값을 n개만 받을 수 있게 조건값이나 초기값 조심하기
// 실수로 i=0부터 n+1 미만까지로 했다가 런타임에러 났음..
for(int i=1;i<n+1;i++)
{
int num=sc.nextInt();
int left=sc.nextInt();
int right=sc.nextInt();
tree[num].left=left;
tree[num].right=right;
if(left!=-1) tree[left].parent=num; //부모가 있는 경우 작성
if(right!=-1) tree[right].parent=num; //부모가 있는 경우 작성
}
for(int i=0;i<n+1;i++)
{
if(tree[i].parent==-1) root=i; // root는 부모가 없는 노드
}
indexNum=1;
dfs(tree[root],1); // root노드는 레벨 1, root 부터 시작
int max_width=0;
int max_index=0;
// 최대 너비와 그 레벨 구하기
for(int i=1;i<n+1;i++)
{
if(max_width<max[i]-min[i]+1)
{
max_width=max[i]-min[i]+1;
max_index=i;
}
}
System.out.println(max_index+" "+max_width);
}
static class Node
{
int parent;
int left;
int right;
Node()
{
// 부모가 없는 경우를 찾기 위해 생성자를 통해 parent 값을 -1로 초기화
this.parent=-1;
this.left=-1;
this.right=-1;
}
}
static void dfs(Node node, int level)
{
//중위 순환(왼쪽노드->부모노드->오른쪽노드로 순환)
//먼저 왼쪽 노드 비었는지 확인
if(node.left!=-1)
{
//왼쪽 노드가 있다면 왼쪽 노드로 진입
dfs(tree[node.left],level+1);
}
//왼쪽에 있는 노드들 모두 확인 후
// 노드에 대한 열 값 최대,최소 저장하기
if(indexNum<min[level])
min[level]=indexNum;
if(indexNum>max[level])
max[level]=indexNum;
//indexNum은 역할을 다하면 1 증가
indexNum++;
//오른쪽 노드 탐색
if(node.right!=-1)
dfs(tree[node.right],level+1);
}
}

'IT > 알고리즘' 카테고리의 다른 글
백준 알고리즘 | 14501 | 퇴사ㅣJava (2) (0) | 2021.07.25 |
---|---|
백준 알고리즘 | 14501 | 퇴사ㅣJava (1) (0) | 2021.07.25 |
백준 알고리즘 | 2468 | 안전 영역ㅣJava (0) | 2021.07.21 |
백준 알고리즘 | 1946 | 신입 사원ㅣJava (0) | 2021.07.20 |
백준 알고리즘 | 1339 | 단어 수학ㅣJava (0) | 2021.07.20 |