[JAVA] 9934 - 완전 이진 트리 🩶1 : 트리 탐색은 index 기반으로 탐색하자.

2026. 2. 22. 15:26·Problem Solve

들어가며

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

문제의 입력값으로 트리의 높이(K)와 중위순회(InOrder)로 탐색한 노드가 순서대로 주어진다. 이를 레벨별로 다시 구성하여 출력하면 된다. 문제의 요구사항은 단순했는데, 너무 무식하게 풀어서 내 풀이와 다른분들의 풀이를 비교하면서 글을 적어본다.

본문으로

처음에는 InOrder로 순회한 것을 어떻게 레벨별로 다시 구성하지? 라는 생각과 함께 아이디어가 떠오르지 않아서 그려보았다.

역시 직접 손으로 그려보니 바로 아이디어가 보였다. 리스트를 반으로 잘라서 그 절반에 있는 값이 그 레벨에 속하는 값이구나..! 생각이 들었다. 그래서 바로 리스트를 반으로 잘라가며 넘겨야겠다. 라는 생각에 아래와 리스트를 복사해가며 로직을 구성했다.

public class Main {

    static int K;
    static List<Integer>[] answer;

    static void go(int idx, List<Integer> beforeList, List<Integer> afterList) {
        if (beforeList.size() == 1 && afterList.size() == 1) {
            answer[idx].add(beforeList.get(0));
            answer[idx].add(afterList.get(0));
            return;
        }

        answer[idx].add(beforeList.get(beforeList.size() / 2));
        answer[idx].add(afterList.get(afterList.size() / 2));

        List<Integer> aBeforeList = new ArrayList<>();
        List<Integer> aAfterList = new ArrayList<>();
        List<Integer> bBeforeList = new ArrayList<>();
        List<Integer> bAfterList = new ArrayList<>();

        for (int i = 0; i < beforeList.size() / 2; i++) {
            aBeforeList.add(beforeList.get(i));
        }
        for (int i = beforeList.size() / 2 + 1; i < beforeList.size(); i++) {
            aAfterList.add(beforeList.get(i));
        }
        for (int i = 0; i < afterList.size() / 2; i++) {
            bBeforeList.add(afterList.get(i));
        }
        for (int i = afterList.size() / 2 + 1; i < afterList.size(); i++) {
            bAfterList.add(afterList.get(i));
        }

        go(idx + 1, aBeforeList, aAfterList);
        go(idx + 1, bBeforeList, bAfterList);

    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        K = Integer.parseInt(bf.readLine());
        answer = new ArrayList[K];
        for (int i = 0; i < K; i++) {
            answer[i] = new ArrayList<>();
        }

        int size = 2;
        for (int i = 0; i < K - 1; i++) {
            size *= 2;
        }
        size -= 1;

        StringTokenizer st = new StringTokenizer(bf.readLine());
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            list.add(Integer.parseInt(st.nextToken()));
        }

        answer[0].add(list.get(size / 2));
        List<Integer> beforeList = new ArrayList<>();
        List<Integer> afterList = new ArrayList<>();
        for (int i = 0; i < size / 2; i++) {
            beforeList.add(list.get(i));
        }
        for (int i = size / 2 + 1; i < size; i++) {
            afterList.add(list.get(i));
        }

        go(1, beforeList, afterList);

        for (int i = 0; i < K; i++) {
            for (int j = 0; j < answer[i].size(); j++) {
                System.out.print(answer[i].get(j) + " ");
            }
            System.out.println();
        }
    }
}

보면.. 리스트를 슬라이싱하는 법을 몰라서 그냥.. 새로 만들어서 원하는 만큼 담아준 다음에 인자로 넘겨줬다. 다행히도 시간초과는 나지 않고 정답이었다. 하지만 이 문제가 제한시간을 넉넉하게 줘서 다행이지, 매번 List<> 자료구조를 생성하는 것은 비효율적인 것 같았다.


그래서 다른 분들 풀이를 참고해보니, 아니나 다를까 나처럼 리스트를 통째로 넘기는 분은 거의 없고 대부분 원본 리스트에서 인덱스를 가지고 구현하셨다... 왜 그생각을 못했을까? 아래는 참고하여 인덱스 기반으로 다시 구현한 로직이다.

public class Main {

    static int K;
    static List<Integer>[] answer;
    static List<Integer> tree;

    static void go(int level, int start, int end) {
        if (level == K || start > end) {
            return;
        }

        int mid = (start + end) / 2;
        answer[level].add(tree.get(mid));

        go(level + 1, start, mid - 1);
        go(level + 1, mid + 1, end);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        K = Integer.parseInt(bf.readLine());
        answer = new ArrayList[K];
        for (int i = 0; i < K; i++) {
            answer[i] = new ArrayList<>();
        }

        int size = 2;
        for (int i = 0; i < K - 1; i++) {
            size *= 2;
        }
        size -= 1;

        StringTokenizer st = new StringTokenizer(bf.readLine());
        tree = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            tree.add(Integer.parseInt(st.nextToken()));
        }

        go(0, 0, size - 1);

        for (int i = 0; i < K; i++) {
            for (int j = 0; j < answer[i].size(); j++) {
                System.out.print(answer[i].get(j) + " ");
            }
            System.out.println();
        }
    }
}

이렇게 인덱스 기반으로 한다면 각 원소를 answer배열에 딱 한번만 넣으므로 O(N)으로 시간복잡도를 유지할 수 있다. 원래 내 풀이는.. 레벨마다 리스트를 복사하므로 대략 O(N log N) 정도로 시간복잡도가 불어난 풀이었다.

마무리하며

트리 관련된 문제가 나오면 괜히 어려워 보이는데, 인덱스 기반으로 잘 생각해보자! 트리 문제는 전공자라면 잘 풀어야 하지 않겠는가!!

'Problem Solve' 카테고리의 다른 글

[JAVA] 14620 - 꽃길 🩶2: 방문배열을 야무지게 활용하는 완탐 문제  (1) 2026.02.24
[JAVA] 15684 - 사다리 타기 💛3 : 백트래킹을 하지 않으면 풀리지 않는 완전탐색 문제  (0) 2026.02.23
[JAVA] 3197 - 백조의 호수 💚5 : 방문배열 대신 Queue를 여러개 사용하여 탐색범위를 지정하자. (BFS + 플러드필)  (0) 2026.02.20
[JAVA] 14497 - 주난의 난 💛 4 : Deque를 활용한 BFS 활용 문제  (0) 2026.02.19
[JAVA] 17071 - 숨바꼭질5 💚5 : 아이디어가 필요한 BFS 문제 + 플러드필  (0) 2026.02.18
'Problem Solve' 카테고리의 다른 글
  • [JAVA] 14620 - 꽃길 🩶2: 방문배열을 야무지게 활용하는 완탐 문제
  • [JAVA] 15684 - 사다리 타기 💛3 : 백트래킹을 하지 않으면 풀리지 않는 완전탐색 문제
  • [JAVA] 3197 - 백조의 호수 💚5 : 방문배열 대신 Queue를 여러개 사용하여 탐색범위를 지정하자. (BFS + 플러드필)
  • [JAVA] 14497 - 주난의 난 💛 4 : Deque를 활용한 BFS 활용 문제
노을을
노을을
진인사대천명
  • 노을을
    노을의 개발일기장
    노을을
  • 전체
    오늘
    어제
    • All (105) N
      • Java & Kotlin (16)
      • Problem Solve (46)
      • Spring (4)
      • Infra (3) N
      • DB (2)
      • Project (2)
        • SOMA (1)
        • OJik (1)
      • OpenSource (3)
      • Various Dev (23)
        • 우아한테크코스 (9)
        • Git&Github (2)
        • Unity (12)
      • Book (3)
      • Writing (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    합격
    개발
    우아한테크코스
    알고리즘
    프리코스
    비트마스킹
    백준
    시뮬레이션
    오픈소스
    github
    게임개발
    유니티
    8기
    contribute
    개발자
    코테
    java
    자바
    코딩
    트러블슈팅
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
노을을
[JAVA] 9934 - 완전 이진 트리 🩶1 : 트리 탐색은 index 기반으로 탐색하자.
상단으로

티스토리툴바