관리 메뉴

Partially Committed

[InOrder 와 PostOrder λ‘œλΆ€ν„° PreOrder κ΅¬ν•˜κΈ°] λ°±μ€€ 2263 트리의 순회 (JAVA) λ³Έλ¬Έ

πŸ”₯ Algorithm || λ¬Έμ œν’€μ΄/PS

[InOrder 와 PostOrder λ‘œλΆ€ν„° PreOrder κ΅¬ν•˜κΈ°] λ°±μ€€ 2263 트리의 순회 (JAVA)

WonderJay 2023. 3. 22. 16:31
728x90
λ°˜μ‘ν˜•
SMALL

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

 

2263번: 트리의 순회

첫째 쀄에 n(1 ≤ n ≤ 100,000)이 주어진닀. λ‹€μŒ μ€„μ—λŠ” μΈμ˜€λ”λ₯Ό λ‚˜νƒ€λ‚΄λŠ” n개의 μžμ—°μˆ˜κ°€ 주어지고, κ·Έ λ‹€μŒ μ€„μ—λŠ” 같은 μ‹μœΌλ‘œ ν¬μŠ€νŠΈμ˜€λ”κ°€ 주어진닀.

www.acmicpc.net

μž¬κ·€λŠ” 항상 μ–΄λ €μš΄ 것 κ°™λ‹€.. πŸ₯Ί

 

μœ„ λ¬Έμ œλŠ” 쑰금 νŠΉμ΄ν•œλ°,

 

InOrder Traverse 와 PostOreder Traverse κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ PreOrder Traverse λ₯Ό 좜λ ₯ν•˜λŠ” 것이 μš”κ΅¬ 사항이닀.

 

음..

 

일단 Tree 의 μˆœνšŒμ—μ„œ 기쀀이 λ˜λŠ” 것은 Root λ…Έλ“œμ΄λ‹€.

 

InOrder 와 PostOrder λŠ” μ£Όμ–΄μ§€λŠ”λ°,

 

μ΄λ‘œλΆ€ν„° Root λ…Έλ“œλ₯Ό μ–΄λ–»κ²Œ 찾을 수 μžˆμ„κΉŒ?

 

PostOrder λŠ” left - right - root 순으둜 μˆœνšŒν•˜λ―€λ‘œ PostOrder 둜 주어진 κ°’λ“€μ˜ κ°€μž₯ λ§ˆμ§€λ§‰μ΄ Root λ…Έλ“œμž„μ„ μ•Œ 수 μžˆλ‹€.

 

InOrder λŠ” left - root - right 순으둜 μˆœνšŒν•œλ‹€.

 

그러면 PostOrder 을 톡해 얻은 Root λ…Έλ“œμ˜ 값을 μ΄μš©ν•˜μ—¬,

 

InOrder μˆœμ„œ μ€‘μ—μ„œ Root λ…Έλ“œλ₯Ό λͺ‡ 번째 λ°©λ¬Έν•˜λŠ” 지 ν™•μΈν•˜λ©΄ (RootIdx)  

 

Left Subtree 와 Right Subtree λ₯Ό μ–»μ–΄λ‚Ό 수 μžˆλ‹€.

 

μ–΄λ–»κ²Œ?

 

InOrder λ°°μ—΄μ˜ 0~RootIdx-1 κΉŒμ§€ = Left Subtree 

 

InOrder λ°°μ—΄μ˜ RootIdx ~ n-1 κΉŒμ§€ = Right Subtree

 

그리고 각각의 Subtree 에 λŒ€ν•΄μ„œ μœ„ μž‘μ—…μ„ λ°˜λ³΅ν•΄μ£Όλ©΄ λœλ‹€.

 

μ–Έμ œκΉŒμ§€? (terminate condition)

 

더이상 λ°©λ¬Έν•  수 μžˆλŠ” λ…Έλ“œκ°€ 없을 λ•Œ κΉŒμ§€!

 

이제 μ½”λ“œλ‘œ κ΅¬ν˜„ν•΄λ³΄μž.

 

ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜λŠ”

 

ν˜„μž¬ Depth μ—μ„œ InOrder 의 μ‹œμž‘μ§€μ  : InLeft

ν˜„μž¬ Depth μ—μ„œ InOrder 의 끝지점 : InRight

ν˜„μž¬ Depth μ—μ„œ PostOrder 의 μ‹œμž‘μ§€μ  : PostLeft

ν˜„μž¬ Depth μ—μ„œ PostOrder 의 끝지점 : PostRight

static void printPreOrder(int inLeft, int inRight, int postLeft, int postRight) throws  IOException 

 κ·Έλ¦¬κ³  terminate condition 은 더이상 탐색할 λ…Έλ“œκ°€ 없을 λ•Œ μ’…λ£Œν•œλ‹€.

if(inLeft > inRight || postLeft > postRight)
    return;

root λ…Έλ“œλŠ” postOrder λ°°μ—΄μ˜ κ°€μž₯ 끝에 μžˆλŠ” 값이닀.

int root = postOrder[postRight];

μœ„ root λ…Έλ“œλ₯Ό μ΄μš©ν•˜μ—¬ InOrder μ—μ„œ left subtree 와 Right subtree λ₯Ό λΆ„λ¦¬ν•˜λŠ” 것이 1차적인 λͺ©μ μ΄λ‹€.

 

이λ₯Ό μœ„ν•΄μ„œλŠ” InOrder μ—μ„œ ν˜„μž¬ Depth μ—μ„œμ˜ root λ…Έλ“œλ₯Ό λͺ‡ 번째둜 νƒμƒ‰ν•˜λŠ” 지 Index λ₯Ό μ•Œμ•„λ‚΄μ•Ό ν•œλ‹€.

 

κ°„λ‹¨ν•˜κ²Œ Linear search 둜 κ΅¬ν˜„ν•˜μ˜€λ‹€.

int rootIdx = 0;
for(int i = inLeft; i<=inRight; i++){
    if(inOrder[i] == root){
        rootIdx = i;
    }
}

그리고 ν˜„μž¬ Depth μ—μ„œ root λ…Έλ“œλ₯Ό 좜λ ₯ν•œλ‹€.

bw.write(inOrder[rootIdx]+" ");

이제 RootIdx λ₯Ό μ΄μš©ν•˜μ—¬ LeftSubTree , RightSubTree 의 Size λ₯Ό 계산할 수 μžˆλ‹€.

 

left - root - right 순으둜 νƒμƒ‰ν•˜λŠ” InOrder 의 νŠΉμ„±μ„ μ΄μš©ν•˜λ©΄ λ˜λŠ”λ°,

 

InOrder μ—μ„œ root λ…Έλ“œλŠ” rootIdx 번째둜 νƒμƒ‰ν•˜λ―€λ‘œ

 

leftSubTree 의 size λŠ” rootIdx - inLeft

rightSubTree 의 size λŠ” inRight - rootIdx 이닀.

 

이제 각각의 μ„œλΈŒνŠΈλ¦¬μ— λŒ€ν•΄μ„œ μž¬κ·€μ μœΌλ‘œ λ™μΌν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜μž.

 

λ¨Όμ € left SubTree 에 λŒ€ν•΄μ„œ μƒκ°ν•΄λ³΄μž.

 

inOrder λ°°μ—΄μ˜ μ‹œμž‘μ μ€ 동일할 것이닀. 

inOrder λ°°μ—΄μ˜ 끝점은 Root 의 μ΄μ „κΉŒμ§€μ΄λ‹€. (rootIdx-1)

PostOrder λ°°μ—΄μ˜ μ‹œμž‘μ μ€ 동일할 것이닀.

PostOrder λ°°μ—΄μ˜ 끝점은 PostOrder λ°°μ—΄μ˜ μ‹œμž‘μ μ—μ„œ leftSubTree 의 size 만큼 λ”ν•œ λ’€ 1 을 λΊ€ 것이닀. (0 - index)

     PostLeft + leftSubtreeSize 라고 ν•˜λ©΄ Root λ…Έλ“œλ₯Ό ν¬ν•¨ν•˜κ²Œ λœλ‹€. 

printPreOrder(inLeft, rootIdx - 1, postLeft, postLeft + leftSubtreeSize - 1);

Right SubTree 에 λŒ€ν•΄μ„œ 생각해보면,

 

InOrder λ°°μ—΄μ˜ μ‹œμž‘μ μ€ root λ…Έλ“œμ˜ λ‹€μŒλΆ€ν„°μΌ 것이닀.

InOrder λ°°μ—΄μ˜ 끝점은 InRight 둜 동일할 것이닀.

PostOrder λ°°μ—΄μ˜ μ‹œμž‘μ μ€ postLeft μ—μ„œ leftsubTreeSize λ₯Ό λ”ν•œ 것이닀.

postRight λŠ” Root λ…Έλ“œλ₯Όμ œμ™Έν•œ PostRight - 1 κΉŒμ§€ 일 것이닀.

printPreOrder(rootIdx + 1, inRight, postLeft + leftSubtreeSize, postRight - 1);

인덱싱이 되게 ν—·κ°ˆλ¦¬λŠ”λ°(1을 λΉΌμ•Ό 할지 더해야 할지), 그림을 그렀놓고 루트 λ…Έλ“œλ₯Ό ν¬ν•¨ν•˜μ§€ μ•Šλ„λ‘ ν•΄μ•Όν•œλ‹€λŠ” 것을 μƒκ°ν•˜λ©΄ λͺ‡ 번의 μ‹œν–‰μ°©μ˜€λ₯Ό κ±°μ³μ„œ ν•΄κ²°ν•  수 μžˆμ„ 것이닀..! 😒

 

전체 μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™λ‹€.

import javax.lang.model.SourceVersion;
import java.io.*;
import java.util.*;

public class Main {
    static int n;
    static int[] inOrder;
    static int[] postOrder;
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) throws IOException {
        System.setIn(new FileInputStream("src/input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stk;

        n = Integer.parseInt(br.readLine());
        inOrder = new int[100001];
        postOrder = new int[100001];

        stk = new StringTokenizer(br.readLine());
        for (int i = 0; i < n; i++) {
            inOrder[i] = Integer.parseInt(stk.nextToken());
        }

        stk = new StringTokenizer(br.readLine());
        for (int i = 0; i < n; i++) {
            postOrder[i] = Integer.parseInt(stk.nextToken());
        }

        printPreOrder(0, n-1, 0, n-1);

        bw.flush();
        bw.close();
    }
    static void printPreOrder(int inLeft, int inRight, int postLeft, int postRight) throws  IOException {
        if(inLeft > inRight || postLeft > postRight)
            return;
        int root = postOrder[postRight];
        int rootIdx = 0;
        for(int i = inLeft; i<=inRight; i++){
            if(inOrder[i] == root){
                rootIdx = i;
            }
        }
        bw.write(inOrder[rootIdx]+" ");

        int leftSubtreeSize = rootIdx - inLeft;

        printPreOrder(inLeft, rootIdx - 1, postLeft, postLeft + leftSubtreeSize - 1);
        printPreOrder(rootIdx + 1, inRight, postLeft + leftSubtreeSize, postRight - 1);
    }


}

 

 

728x90
λ°˜μ‘ν˜•
LIST
Comments