https://www.acmicpc.net/problem/9934
Tree
+ 재귀 함수배열 int[] tree
에 트리 노드들 저장
중위 순회 순서에서 루트 노드: 중간에 방문
1) 루트 노드
inorder[(2^k - 1) / 2]
가 루트 노드인 tree[1]
이 됨2) 찾은 부모 노드를 기준으로, Left / Right Subtree 각각에서 부모 노드찾음
[i]
이면[0]
~ [i-1]
의 중간 index[i+1]
~ [끝]
의 중간 index이분 탐색(Binary Search) 하듯이 중간 index(부모) 기준으로 2개 Subtree
recursive(startIdx, endIdx)
로 중위 순회에서 부모 index 찾음
=> 재귀 종료 조건: Leaf 노드까지 내려간 경우
트리에서 부모 index 가 [i]
이면 (루트 노드는 [1]
)
[i * 2]
[i * 2 + 1]
int[]
: 입력 값, 중위 순회 순서 저장[0 ~ ]
사용int[]
: 출력 값, 트리 저장[1 ~ ]
사용import java.io.*;
import java.util.StringTokenizer;
public class Main_Recursive1 {
static int k; // 완전 이진 트리의 depth
static int nodeCount; // 총 노드 개수: 2^k - 1
static int[] inorder; // 입력: Inorder Traversal (중위 순회) 방문 순서
static int[] tree; // 출력: 트리 (루트 노드: tree[1])
/* startIdx, endIdx: 중위 순회 순서 inorder[]에서의 index */
/* treeIdx: 출력 배열 tree[]에 채울 index */
static void recursive(int startIdx, int endIdx, int treeIdx) {
// 주어진 범위 start ~ end 에서, 중위 순회 inorder[] 의 부모 노드를 찾음
int parentIdx = (startIdx + endIdx) / 2;
tree[treeIdx] = inorder[parentIdx];
int leftChildIdx = treeIdx * 2;
int rightChildIdx = treeIdx * 2 + 1;
// 재귀 종료 조건: Leaf 노드까지 내려간 경우
if (startIdx == endIdx)
return;
recursive(startIdx, parentIdx - 1, leftChildIdx); // left subtree
recursive(parentIdx + 1, endIdx, rightChildIdx); // right subtree
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
k = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
nodeCount = (int)Math.pow(2, k) - 1;
inorder = new int[nodeCount]; // [0 ~ 노드 개수 - 1] 사용
tree = new int[nodeCount + 1]; // [1 ~ 노드 개수] 사용
for (int i = 0; i < inorder.length; i++)
inorder[i] = Integer.parseInt(st.nextToken());
// 루트 노드 tree[1] 에서부터 시작
recursive(0, nodeCount - 1, 1);
// 트리의 Depth (Level) 단위로 개행하여 출력
StringBuilder sb = new StringBuilder();
for (int level = 1; level <= k; level++) {
// 현재 level 까지 속하는 노드 개수
// e.g. level 2 까지 => 2^2 - 1 = 3개
int currentNodeCount = (int)Math.pow(2, level) - 1;
int prevNodeCount = (int)Math.pow(2, level - 1) - 1;
for (int i = prevNodeCount + 1; i <= currentNodeCount; i++)
sb.append(tree[i]).append(" ");
sb.append("\n");
}
System.out.println(sb);
}
}
Tree
+ 재귀 함수트리 Level 단위로 StringBuilder[]
에 저장 (Level Order Traversal)
중위 순회 순서에서 루트 노드: 중간에 방문
1) 루트 노드
inorder[(2^k - 1) / 2]
가 루트 노드인 tree[1]
이 됨2) 찾은 부모 노드를 기준으로, Left / Right Subtree 각각에서 부모 노드찾음
[i]
이면[0]
~ [i-1]
의 중간 index[i+1]
~ [끝]
의 중간 index이분 탐색(Binary Search) 하듯이 중간 index(부모) 기준으로 2개 Subtree
recursive(startIdx, endIdx)
로 중위 순회에서 부모 index 찾음
=> 재귀 종료 조건: Leaf 노드까지 내려간 경우
트리에서 부모 index 가 [i]
이면 (루트 노드는 [1]
)
[i * 2]
[i * 2 + 1]
int[]
: 입력 값, 중위 순회 순서 저장[0 ~ ]
사용StringBuilder[]
: 출력 값, 트리 Level 단위로 노드들 저장import java.io.*;
import java.util.StringTokenizer;
public class Main_Recursive2 {
static int k; // 완전 이진 트리의 depth
static int nodeCount; // 총 노드 개수: 2^k - 1
static int[] inorder; // 입력: Inorder Traversal (중위 순회) 방문 순서
static StringBuilder[] sbArr;
// 출력: 트리 Level 단위로 노드들 저장
// e.g. sbArr[1] => Level 1 루트 노드
/* startIdx, endIdx: 중위 순회 순서 inorder[]에서의 index */
/* level: 트리의 level, 저장할 StringBuilder[] 의 index */
static void recursive(int startIdx, int endIdx, int level) {
// 재귀 종료 조건: Leaf 노드까지 내려간 경우
if (level > k)
return;
int parentIdx = (startIdx + endIdx) / 2;
sbArr[level].append(inorder[parentIdx]).append(" ");
recursive(startIdx, parentIdx - 1, level + 1); // left subtree
recursive(parentIdx + 1, endIdx, level + 1); // right subtree
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
k = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
nodeCount = (int)Math.pow(2, k) - 1;
inorder = new int[nodeCount]; // [0 ~ 노드 개수 - 1] 사용
sbArr = new StringBuilder[nodeCount + 1]; // [1 ~ 노드 개수] 사용
for (int i = 1; i < sbArr.length; i++)
sbArr[i] = new StringBuilder();
for (int i = 0; i < inorder.length; i++)
inorder[i] = Integer.parseInt(st.nextToken());
// Level 1, 루트 노드에서부터 시작
recursive(0, nodeCount - 1, 1);
// 트리의 Depth (Level) 단위로 개행하여 출력
StringBuilder sb = new StringBuilder();
for (int i = 1; i < sbArr.length; i++)
sb.append(sbArr[i]).append("\n");
System.out.println(sb);
}
}
Tree
+ Queue
트리의 Level 단위로 Queue
에 노드 추가 (Level Order Traversal)
중위 순회 순서에서 루트 노드: 중간에 방문
1) 루트 노드
inorder[(2^k - 1) / 2]
가 루트 노드인 tree[1]
이 됨2) 찾은 부모 노드를 기준으로, Left / Right Subtree 각각에서 부모 노드찾음
[i]
이면[0]
~ [i-1]
의 중간 index[i+1]
~ [끝]
의 중간 index이분 탐색(Binary Search) 하듯이 중간 index(부모) 기준으로 2개 Subtree
트리에서 부모 index 가 [i]
이면 (루트 노드는 [1]
)
[i * 2]
[i * 2 + 1]
int[]
: 입력 값, 중위 순회 순서 저장[0 ~ ]
사용Queue<Pair>
, LinkedList<Pair>
: 트리 Level 단위로 inorder[]
에서 탐색할 Pair (startIdx, endIdx)
저장import java.io.*;
import java.util.*;
class Pair {
public int startIdx, endIdx;
public Pair(int startIdx, int endIdx) {
this.startIdx = startIdx;
this.endIdx = endIdx;
}
}
public class Main_Queue {
static int k; // 완전 이진 트리의 depth
static int nodeCount; // 총 노드 개수: 2^k - 1
static int[] inorder; // 입력: Inorder Traversal (중위 순회) 방문 순서
static StringBuilder sb = new StringBuilder(); // 출력 값: 트리의 Level 단위로 노드들 저장
static Queue<Pair> queue = new LinkedList<>(); // 트리의 Level 단위로 노드들을 Queue 에 추가
static void solution() {
while (!queue.isEmpty()) {
// 현재 트리 Level 의 노드 개수
int currentNodeCount = queue.size();
for (int i = 0; i < currentNodeCount; i++) {
Pair p = queue.remove();
int parentIdx = (p.startIdx + p.endIdx) / 2;
sb.append(inorder[parentIdx]).append(" ");
// p.startIdx == p.endIdx 인 경우, Leaf 노드까지 내려감
if (p.startIdx != p.endIdx) {
queue.add(new Pair(p.startIdx, parentIdx - 1)); // left subtree
queue.add(new Pair(parentIdx + 1, p.endIdx)); // right subtree
}
}
sb.append("\n");
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
k = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
nodeCount = (int)Math.pow(2, k) - 1;
inorder = new int[nodeCount]; // [0 ~ 노드 개수 - 1] 사용
for (int i = 0; i < inorder.length; i++)
inorder[i] = Integer.parseInt(st.nextToken());
// 루트 노드에서부터 시작
queue.add(new Pair(0, nodeCount - 1));
solution();
System.out.println(sb);
}
}