Algorithm/BOJ

백준 5639 이진 검색 트리

삼쓰 웅쓰 2021. 3. 26. 14:19
728x90

출처: www.acmicpc.net/problem/5639

분류: 트리


접근방식

pre-order 결과가 들어오면 이 트리의 post-order 검색의 결과를 출력하는 문제였습니다.

pre-order의 결과를 놓고 보면

첫 번째가 root
root+1 부터 처음으로 root보다 큰 값이 나오는 위치까지가 Left
그 다음이 Right 트리가 됩니다.

 

우리가 원하는 결과인 post-order는 왼쪽부터 탐색하기 때문에

루트를 타겟으로 이분탐색으로 UpperBounds를 찾아서 

왼쪽 -> 오른쪽 -> 루트 

를 반복적으로 돌려주면 원하는 결과를 얻을 수 있습니다.

 

처음엔 입력 받을 때마다 루트부터 위치를 찾아 트리를 만들어 나가는 방식으로 접근했었는데 이렇게 하니까 시간초과가 났습니다.
c++로는 이런 식으로 풀어도 통과가 되는 것 같던데 swift는 안 되는건지 제가 뭔갈 잘못했던 것인지를 모르겠네요.. 😢

해결방법

 


import Foundation

var preOrderList = [Int]()
while let s = readLine(), let n = Int(s) {
  preOrderList.append(n)
}

func binaryUpperBounds(start: Int, end: Int, target compare: Int) -> Int {
  var start = start
  var end = end

  while start < end {
    let mid = (start + end)/2

    if compare < preOrderList[mid] {
      end = mid
    } else {
      start = mid+1
    }
  }
  return start
}

func postOrder(start: Int, end: Int) {
  guard start < end else { return }

  let upperIndex = binaryUpperBounds(start: start+1, end: end, target: preOrderList[start])
  postOrder(start: start+1, end: upperIndex)
  postOrder(start: upperIndex, end: end)
  print(preOrderList[start])
}

postOrder(start: 0, end: preOrderList.count)

 

배운점

어렵지 않은 문제였는데 이걸로 몇 시간을 날린지 모르겠다...

트리를 만들어 나가는 방식으로 했다가 시간초과를 맞고,

마지막까지 입력받은 트리를 currentNode로 두고 다음 위치를 찾아 막 비교해보는 방식으로 하려고도 해봤는데;;
이런 식으로는 현재 노드가 트리의 어느 부분인지 감을 잡을 수 없기 때문에 도저히 찾을 수가 없는 것 같다.... 여기서 얼마나 헤맨건지...

고통스럽다...