https://www.acmicpc.net/problem/5639
입력 전위 순회에서 부모 노드를 찾아서 Left Subtree, Right Subtree 로 나눔
이진 탐색 트리 (Binary Search Tree, BST)
후위 순회 (Postorder): Left Child → Right Child → Parent
입력 preorder 배열에서 루트(부모) 노드를 정하고
Left Subtree, Right Subtree 에 대해 재귀호출
1) Left Subtree: postorder(startIdx + 1, 부모 노드보다 큰 노드의 idx - 1)
2) Right Subtree: postorder(부모 노드보다 큰 노드의 idx + 1, endIdx)
3) 부모 노드 preorder[startIdx] 출력
int[]: 입력, 전위 순회 순서int[10^5]: 4 x 10^5 byte = 0.4 MB=> 전체 최대 노드 수 10^5에 대해 대략 재귀 호출 2번 수행
=> 총 시간 복잡도: 2 x 10^5 << 1억 (1초)
import java.io.*;
public class Main {
static final int MAX_COUNT = 10000;
static int[] preorder = new int[MAX_COUNT]; // 입력: 전위 순회
static StringBuilder sb = new StringBuilder(); // 출력 값, 후위 순회 저장
static void postorder(int startIdx, int endIdx) {
if (startIdx > endIdx)
return;
int parent = preorder[startIdx];
int rightChildIdx;
for (rightChildIdx = startIdx; rightChildIdx <= endIdx; rightChildIdx++) {
if (parent < preorder[rightChildIdx]) // Parent < Right Child
break;
}
postorder(startIdx + 1, rightChildIdx - 1); // Left Subtree
postorder(rightChildIdx, endIdx); // Right Subtree
sb.append(parent).append("\n"); // Parent 출력
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
int idx = 0;
while (true) {
String input = br.readLine();
if (input == null || input.equals(""))
break;
preorder[idx++] = Integer.parseInt(input);
}
postorder(0, idx - 1);
System.out.println(sb);
}
}
이진 탐색 트리
BinarySearchTree를 직접 구현
이진 탐색 트리 (Binary Search Tree, BST)
이진 탐색 트리(BinarySearchTree)를 직접 구현하여 트리 저장,
후위 순회를 재귀 함수로 구현
입력이 전위 순회 순서로 들어오므로, 부모 노드를 기준으로 트리 저장
후위 순회 (Postorder): Left Child → Right Child → Parent
1) 새로 insert 하려는 노드 값 < 부모 노드인 경우
case 1) 부모 노드의 Left Child 가 없는 경우,
새로 Left Child 를 생성하여 삽입
case 2) 부모 노드의 Left Child 가 이미 있는 경우,
이미 존재하는 Left Child 로 내려가서 다시 비교 및 삽입
=> 재귀 호출
2) 새로 insert 하려는 노드 값 > 부모 노드인 경우
case 1) 부모 노드의 Right Child 가 없는 경우,
새로 Right Child 를 생성하여 삽입
case 2) 부모 노드의 Right Child 가 이미 있는 경우,
이미 존재하는 Right Child 로 내려가서 다시 비교 및 삽입
=> 재귀 호출
BinarySearchTree: 이진 탐색 트리 구현1) 이진 탐색 트리 저장
BST의 탐색 / 삽입 시간 복잡도: O(H)
(H: BST 의 높이)
BST가 완전 이진 트리(균형이 완벽하게 잡힌 이진 트리)인 경우: O(H) = O(log2 n)
(n: 노드 개수)
Worst) BST 가 균형이 잡히지 않은 경우 (BST 가 왼쪽 or 오른쪽으로만 길게 뻗은 경우)
: O(H)
=> H 최대값으로 노드의 개수 10^5 개 대입
=> BST 저장 시간 복잡도: 10^5
2) 후위 순회 출력
=> 전체 시간 복잡도 = BST 저장 후, 후위 순회 출력
= 10^5 + (2 x 10^5) = 3 x 10^5 << 1억 (1초)
import java.io.*;
class Node {
public int data; // 부모 노드의 값
public Node leftChild, rightChild;
public Node(int data) {
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}
class BinarySearchTree {
public Node root;
public StringBuilder sb = new StringBuilder();
public BinarySearchTree(Node root) {
this.root = root;
}
public void insert(int data) {
// 루트 노드에서부터 삽입할 위치를 재귀 호출로 찾아서, 새로운 노드 삽입
root = insertBST(root, data);
}
private Node insertBST(Node temp, int data) {
if (temp == null)
temp = new Node(data);
else if (temp.data > data) // Left Subtree
temp.leftChild = insertBST(temp.leftChild, data);
else if (temp.data < data) // Right Subtree
temp.rightChild = insertBST(temp.rightChild, data);
return temp;
}
public void postorder(Node node) {
if (node == null)
return;
postorder(node.leftChild); // Left Subtree
postorder(node.rightChild); // Right Subtree
sb.append(node.data).append("\n"); // Parent 출력
}
}
public class Main_Dev_BST {
static BinarySearchTree bst;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
int rootValue = Integer.parseInt(br.readLine());
bst = new BinarySearchTree(new Node(rootValue));
while (true) {
String input = br.readLine();
if (input == null || input.equals(""))
break;
bst.insert(Integer.parseInt(input));
}
bst.postorder(bst.root);
System.out.println(bst.sb);
}
}