![[BOJ2263] 트리의 순회(분할 정복)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F21Ukx%2FbtsFipezM1L%2FGCNXNtMe1n3R3Cva4nsKa0%2Fimg.png)

문제 링크
https://www.acmicpc.net/problem/2263
2263번: 트리의 순회
첫째 줄에 n(1 ≤ n ≤ 100,000)이 주어진다. 다음 줄에는 인오더를 나타내는 n개의 자연수가 주어지고, 그 다음 줄에는 같은 식으로 포스트오더가 주어진다.
www.acmicpc.net
풀이
postorder(후위 순회, 왼쪽-오른쪽 -루트)
- 항상 root가 마지막에 위치(*특징)
- 트리의 특성상 root를 기준으로 왼쪽/오른쪽 서브트리가 나누어지게 때문에 postorder 통해 트리의 root 파악 가능
inodrer(중위 순회, 왼쪽-루트-오른쪽)
- root를 기준으로 왼쪽/오른쪽 서브 트리가 나누어진다
- postorder로 구한 root 값으로 inorder의 왼쪽/오른쪽 서브 트리를 분할 할 수 있다
분할 정복?
- 큰 문제를 여러 개의 작은 문제로 쪼갠 다음(분할),
- 작은 문제들의 답을 이용해 큰 문제의 답을 구하는 방법(정복)
분할 정복의 과정
- 문제의 크기가 크다면 1개 이상의 부분 문제로 분할
- 문제의 크기가 충분히 작다면 직접 해결
- 부분 문제들의 답을 이용해 전체 문제의 답을 계산
예시
12
8 4 9 2 5 1 10 6 3 11 7 12 -- inorder(중위 순회)
8 9 4 5 2 10 6 11 12 7 3 1 -- postorder(후위 순회)
① postorder에서 root 값을 찾는다
② inorder에서 root값을 기준으로 왼쪽/오른쪽 서브 트리를 나눈다
③ 왼쪽 서브 트리의 길이를 구하여, postorder도 왼쪽/오른쪽 서브 트리를 나눈다
이때 왼쪽/오른쪽 서브 트리를 나누는 행위는 시작점과 끝점 인덱스를 사용하는 것으로 대체한다
제출 코드
import java.util.*;
import java.io.*;
public class Main {
static StringBuilder sb = new StringBuilder();
static InputProcessor inputProcessor = new InputProcessor();
static String BLANK = " ";
static int N;
static int[] IN_ORDER, POST_ORDER, INORDER_IDX;
public static void main(String[] args) throws IOException {
input();
pro();
output();
}
private static void input() {
N = inputProcessor.nextInt();
IN_ORDER = new int[N + 1];
POST_ORDER = new int[N + 1];
for(int i = 1; i <= N; i++) {
IN_ORDER[i] = inputProcessor.nextInt();
}
for(int i = 1; i <= N; i++) {
POST_ORDER[i] = inputProcessor.nextInt();
}
INORDER_IDX = new int[N + 1];
for(int i = 1; i <= N; i++) {
INORDER_IDX[IN_ORDER[i]] = i;
}
}
private static void pro() {
divide(1, N, 1, N); // 분할 정복
}
private static void divide(int inS, int inE, int poS, int poE) {
if(inE < 1 || inE < inS || poE < 1 || poE < poS) return;
int rootValue = POST_ORDER[poE];
int rootIndex = INORDER_IDX[rootValue];
sb.append(rootValue).append(BLANK);
int len = rootIndex - inS;
//왼쪽 서브 트리
divide(inS, rootIndex - 1, poS, poS + len - 1);
//오른쪽 서브 트리
divide(rootIndex + 1, inE, poS + len, poE - 1);
}
private static void output() throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write(sb.toString());
bw.flush();
bw.close();
}
private static class InputProcessor {
BufferedReader br;
StringTokenizer st;
public InputProcessor() {
this.br = new BufferedReader(new InputStreamReader(System.in));
}
public String next() {
while(st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return st.nextToken();
}
public String nextLine() {
String input = "";
try {
input = br.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
return input;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
}
}
추천 문제
전위/중위 순회가 주어지고, 후위 순회를 구하는 문제
https://www.acmicpc.net/problem/4256
4256번: 트리
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 노드의 개수 n이 주어진다. (1 ≤ n ≤ 1,000) BT의 모든 노드에는 1부터 n까지 서로 다른 번호가 매겨져 있다. 다음
www.acmicpc.net
https://www.acmicpc.net/problem/6597
6597번: 트리 복구
창영이는 바이너리 트리를 매우 좋아한다. 그가 가장 좋아하는 게임은 바이너리 트리를 만들고, 노드에 알파벳 대문자를 하나씩 쓰는 것이다. 같은 알파벳을 여러 노드에 쓰지 않는다. 아래는
www.acmicpc.net
중위 순회(In-Order) 응용하여 문제 풀이
https://www.acmicpc.net/problem/2250
2250번: 트리의 높이와 너비
첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다.
www.acmicpc.net
참고.
https://loosie.tistory.com/345
[BOJ] 백준 2263번 트리의 순회 (Java)
#2263 트리의 순회 난이도 : 골드 3 유형 : 트리 / 분할 정복 2263번: 트리의 순회 첫째 줄에 n(1≤n≤100,000)이 주어진다. 다음 줄에는 인오더를 나타내는 n개의 자연수가 주어지고, 그 다음 줄에는 같
loosie.tistory.com
'알고리즘 > 트리' 카테고리의 다른 글
[BOJ1967] 트리의 지름(dfs, 인접 리스트) (0) | 2023.09.21 |
---|---|
[BOJ1167] 트리의 지름 (트리) (0) | 2023.09.07 |
[BOJ 14267] 회사 문화1 (Java, DFS, Tree) (0) | 2023.06.26 |
[BOJ 1068] 트리 (Java, DFS) (0) | 2023.06.26 |
[BOJ 9489] 사촌 (Java, 트리) (0) | 2023.06.26 |

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!