Algorithm/Java
[백준/JAVA] 9934번: 완전 이진 트리
dbfl9911
2024. 7. 13. 23:45
- 정답 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;
// - 중위 순회 문제
public class Main {
static int K; // 트리 깊이 // 2
static int size; // 트리 노드 수
static int[] num; // 초기 중위 순회 결과 저장
static ArrayList<Integer>[] tree; // 각 레벨별로 노드를 저장할 리스트
public static void main(String[] args) throws IOException{
// 입력값 처리
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 결과값 출력
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
K = Integer.parseInt(br.readLine()); // 2
StringTokenizer st = new StringTokenizer(br.readLine()); // 2 1 3
// 1. 트리 총 노드수 계산
// 깊이가 K인 완전 이진 트리는 총 2^K - 1개의 노드로 이루어짐
// k = 2 , 2^2 - 1 = 3개
size = (int) (Math.pow(2, K) - 1); // 3
// num 초기화 // 2 1 3 들어가야함
num = new int[size + 1];
// 3. 레벨별로 노드를 저장할 리스트 초기화
// 트리의 레벨은 1부터 K까지 존재하므로, 0번째 인덱스를 사용하지 않고,
// 1번째 인덱스부터 K번째 인덱스까지 사용하기 위해 배열의 크기를 K + 1로 설정
tree = new ArrayList[K + 1]; // 레벨 1, 레벨 2 ..
for(int i = 0; i <= K; i++) {
tree[i] = new ArrayList<>();
}
// 2. 중위 순회 결과 저장 [2 , 1, 3]
int index = 1;
while(st.hasMoreTokens()){
num[index++] = Integer.parseInt(st.nextToken());
}
// 4. 중위 순회 결과를 이용해 트리 구성 및 각 레벨에 노드 추가
search(1,1, size);
// 각 레벨에 있는 빌딩 정보 bw에 저장
for(int i = 1; i <= K; i++) {
for(int j = 0; j < tree[i].size(); j++) {
bw.write(tree[i].get(j) + " ");
}
bw.newLine();
}
// 결과 출력
bw.flush();
bw.close();
br.close();
}
// 중위 순회 특성을 이용하여 트리를 구성하고 각 레벨에 맞는 빌딩 값들을 저장
private static void search(int depth, int start, int end) {
int mid = (start + end) / 2; // 현재 서브트리의 루트 노드 위치(중간 지점)
tree[depth].add(num[mid]); // 현재 레벨에 루트 노드 추가
// 단말 노드(자식이 없는 노드)일 때 재귀 종료
if(depth == K) return;
// 왼쪽 서브트리 구성
search(depth + 1, start, mid - 1);
// 오른쪽 서브트리 구성
search(depth + 1, mid + 1, end);
}
}
- 코드 설명
[ 문제 해결 순서 ]
- 입력받기
- 트리의 총 노드 수 계산
- 중위 순회 결과 저장
- 레벨별로 노드를 저장할 리스트 초기화
- 중위 순회 결과를 이용해 트리 구성 및 각 레벨에 노드 추가
- 결과 출력
1. 입력받기
// 입력값 처리
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 결과값 출력
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
K = Integer.parseInt(br.readLine()); // 2
StringTokenizer st = new StringTokenizer(br.readLine()); // 2 1 3
2.트리의 총 노드 수 계산
// 1. 트리 총 노드수 계산
// 깊이가 K인 완전 이진 트리는 총 2^K - 1개의 노드로 이루어짐
// k = 2 , 2^2 - 1 = 3개
size = (int) (Math.pow(2, K) - 1); // 3
3.중위 순회 결과 저장
static int[] num; // 초기 중위 순회 결과 저장
...
// num 초기화 // 2 1 3 들어가야함
num = new int[size + 1];
// 2. 중위 순회 결과 저장 [2 , 1, 3]
int index = 1;
while(st.hasMoreTokens()){
num[index++] = Integer.parseInt(st.nextToken());
}
4.레벨별로 노드를 저장할 리스트 초기화
static ArrayList<Integer>[] tree; // 각 레벨별로 노드를 저장할 리스트
...
// 3. 레벨별로 노드를 저장할 리스트 초기화
tree = new ArrayList[K + 1]; // 레벨 1, 레벨 2 ..
for(int i = 0; i <= K; i++) {
tree[i] = new ArrayList<>();
}
[K + 1]인 이유? -> 트리의 레벨은 1부터 K까지 존재하므로, 0번째 인덱스를 사용하지 않고, 1번째 인덱스부터 K번째 인덱스까지 사용하기 위해 배열의 크기를 K + 1로 설정
5. 중위 순회 결과를 이용해 트리 구성 및 각 레벨에 노드 추가
// 4. 중위 순회 결과를 이용해 트리 구성 및 각 레벨에 노드 추가
search(1,1, size);
....
// 중위 순회 특성을 이용하여 트리를 구성하고 각 레벨에 맞는 빌딩 값들을 저장
private static void search(int depth, int start, int end) {
int mid = (start + end) / 2; // 현재 서브트리의 루트 노드 위치(중간 지점)
tree[depth].add(num[mid]); // 현재 레벨에 루트 노드 추가
// 단말 노드(자식이 없는 노드)일 때 재귀 종료
if(depth == K) return;
// 왼쪽 서브트리 구성
search(depth + 1, start, mid - 1);
// 오른쪽 서브트리 구성
search(depth + 1, mid + 1, end);
}
ex) 깊이 3인 완전 이진 트리의 중위 순회 결과가 1 2 3 4 5 6 7인 경우
- 처음 호출: search(1, 1, 7):
- mid = 4: tree[1]에 num[4] (즉, 4)를 추가합니다.
- 왼쪽 서브트리: search(2, 1, 3):
- mid = 2: tree[2]에 num[2] (즉, 2)를 추가합니다.
- 왼쪽 서브트리: search(3, 1, 1):
- mid = 1: tree[3]에 num[1] (즉, 1)를 추가합니다.
- 오른쪽 서브트리: search(3, 3, 3):
- mid = 3: tree[3]에 num[3] (즉, 3)를 추가합니다.
- 오른쪽 서브트리: search(2, 5, 7):
- mid = 6: tree[2]에 num[6] (즉, 6)를 추가합니다.
- 왼쪽 서브트리: search(3, 5, 5):
- mid = 5: tree[3]에 num[5] (즉, 5)를 추가합니다.
- 오른쪽 서브트리: search(3, 7, 7):
- mid = 7: tree[3]에 num[7] (즉, 7)를 추가합니다.
6.결과 출력
// 각 레벨에 있는 빌딩 정보 bw에 저장
for(int i = 1; i <= K; i++) {
for(int j = 0; j < tree[i].size(); j++) {
bw.write(tree[i].get(j) + " ");
}
bw.newLine();
}
// 결과 출력
bw.flush();
bw.close();
br.close();