1일 1PS 92일차!

📚 문제


[골드 1] - 트리의 순회

💡 풀이 과정


  • 우선 트리의 순회에 대해서 살펴보아야한다.

image

  • 중위 순회, Inorder
    • left -> root -> right 순서대로 순회한다.
    • 위 트리에서는 (1) -> (3) -> (4) -> (5) -> (6) -> (7) -> (12) -> (15) -> (16) 순서로 순회한다.

image

  • 전위 순회, Preorder
    • root -> left -> right 순서대로 순회한다.
    • 위 트리에서는 (7) -> (3) -> (1) -> (5) -> (4) -> (6) -> (15) -> (12) -> (16) 순서로 순회한다.

image

  • 후위 순회, Postorder
    • left -> right -> root 순서대로 순회한다.
    • 위 트리에서는 (1) -> (4) -> (6) -> (5) -> (3) -> (12) -> (16) -> (15) -> (7) 순서로 순회한다.


  • 해당 문제에서는 중위 순회와 후위 순회가 주어진다.
    • 하나의 노드는 결국 Left Nodes, Root Node, Right Nodes 3가지로 나뉠 수 있으며 이들의 순서만 순회 방법에 따라 다르다.
    • 중위 순회 : Left Nodes, Root Node, Right Nodes
    • 후위 순회 : Left Nodes, Right Nodes, Root Node
    • 두 순회를 보고 Root Node 를 확정지을 수 있으며 이후 Left Nodes, Right Nodes 에 동일한 작업을 진행하면 된다. 즉, 재귀함수를 사용할 수 있다.
  • 우선 재귀함수의 종료 조건을 먼저 작성한다. inOrder 존재 여부를 사용했다.
  • 이후 root 는 주어진 postOrder 의 마지막 요소임이 확정이다.
  • 또한 해당 요소의 inOrder 에서의 index 값을 통해 Left Nodes, Right Nodes 를 구분지을 수 있다.
  • Left 와 Right 에 대해서 재귀함수를 진행하며 Right 에서는 root 의 위치에 주의한다.
  • Print 와 left, right 처리 순서에 대해서도 후위 순회 조건에 맞게 배치한다.

  • 처음에는 배열을 넘겼다가 메모리 초과로 인해 index 를 넘겼다.
    • 이때 index 로 넘긴다면 postOrder 의 index 넘김에 주의해야하는데, inOrder 를 통해 Left Nodes 의 개수를 파악해 설정해야 한다.

📌포인트


  • TLE
    • 기존에는 rootInIdx = inOrder.index(root) 를 사용해 index 를 구했다.
    • 이는 O(n^2) 로 시간초과를 발생시켰다.
    • 이후 중위 순회의 인덱스만 기록하는 테이블을 생성해 시간복잡도를 낮췄다.

💻 코드


import sys
sys.setrecursionlimit(1000000)

n = int(input())
inOrder = list(map(int, input().split()))
postOrder = list(map(int, input().split()))

# 중위 순회의 값과 인덱스를 저장하는 해시 테이블
inOrder_index = {val: idx for idx, val in enumerate(inOrder)}

answer = ""

def preOrder(inOrder_start, inOrder_end, postOrder_start, postOrder_end):
    global answer

    if inOrder_start > inOrder_end or postOrder_start > postOrder_end:
        return

    root = postOrder[postOrder_end]
    answer += str(root) + " "

    rootInIdx = inOrder_index[root]

    preOrder(inOrder_start, rootInIdx - 1, postOrder_start, postOrder_start + (rootInIdx - inOrder_start) - 1)
    preOrder(rootInIdx + 1, inOrder_end, postOrder_start + (rootInIdx - inOrder_start), postOrder_end - 1)



preOrder(0, n - 1,0, n - 1)
print(answer)

업데이트:

댓글남기기