Algorithm/BOJ

[BOJ] #5639 이진 검색 트리

jHoon0223 2024. 1. 5. 19:16

https://www.acmicpc.net/problem/5639

 

5639번: 이진 검색 트리

트리를 전위 순회한 결과가 주어진다. 노드에 들어있는 키의 값은 106보다 작은 양의 정수이다. 모든 값은 한 줄에 하나씩 주어지며, 노드의 수는 10,000개 이하이다. 같은 키를 가지는 노드는 없다

www.acmicpc.net


문제 요구조건은 꽤 간단하다. 전위순회로 주어진 트리를 후위순회로 변환하면 끝이다. 이때 중요한 키 포인트는 세가지가 있다. 

1. 전위순회에서 가장 첫번째 노드는 루트 노드이다.
2. 전위순회에서 루트노드보다 커지는 첫번째 원소를 기점으로 왼쪽, 오른쪽 자식트리가 나뉘게 된다.
3. 나뉜 자식트리에 대하여 1~2의 과정을 재귀 형태로 반복하고, 그 과정에서 맨 첫번째 노드(루트 노드)들을 출력해주면 자연스럽게 후위순회로 변환된다.

 

이게 말로 하면 좀 이해가 어려울수가 있는데, 그림을 직접 그려보면 이해가 훨 수월하다.

좀 별로긴 하다.

같은 색으로 표시 된 부분이 루트와 자식트리의 분기점이다. 결과적으로 재귀의 형태를 통해 자식트리들에 대해 같은 동작은 반복하게 되면, 결국 왼쪽 트리의 맨 왼쪽 자식노드가 출력값의 맨 앞에 위치하게 되고, 원래 맨 첫번째 원소였던 루트노드는 맨 뒤에 위치하게 된다.

이렇게 글로 쓰고나니 더 이해가 안되는 느낌인데, 추후에 한번 더 풀어봐야겠다. 커밋 메세지에 애스터리스크 달아 놨으니 참고.

아 그리고, 한가지 더 신경쓸것은 문제에서 주어지는 입력에 대해 명확한 입력종료 조건을 제시하지 않았다. 따라서, 입력 받을때에 while 조건에 cin 입력함수를 넣어 EOF 입력받도록 작성하였고, 그 때문인지는 모르겠지만 시간초과가 두번씩 났었다. 분명 같은 알고리즘을 풀었는데 조금씩 코드를 고치고 고치니까 또 맞혔습니다가 떴다. 뭐지...

#include <iostream>

using namespace std;

int arr[10001];

void F(int start, int end) {
    if (start >= end) return;

    int root = arr[start];
    int idx = start+1;

    while(idx < end){
        if(root < arr[idx]) break;
        idx++;
    }

    F(start+1, idx);
    F(idx, end);

    cout << arr[start] << '\n';
}

int main() {
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);

    int a;
    int n=0;

    while(cin >> a) arr[n++] = a;

    F(0, n);

    return 0;
}

728x90

'Algorithm > BOJ' 카테고리의 다른 글

[BOJ] #2606 바이러스  (0) 2024.01.08
[BOJ] #1260 DFS와 BFS  (0) 2024.01.06
[BOJ] #1991 트리 순회  (0) 2024.01.05
[BOJ] #11723 집합  (0) 2024.01.04
[BOJ] #1302 베스트셀러  (0) 2023.12.20