문제 링크
20551번: Sort 마스터 배지훈의 후계자
지훈이는 Sort 마스터다. 오랫동안 Sort 마스터 자리를 지켜온 지훈이는 이제 마스터 자리를 후계자에게 물려주려고 한다. 수많은 제자들 중에 후계자를 고르기 위해서 지훈이는 제자들에게 문제
www.acmicpc.net

문제 해설
사용 알고리즘 : 이진탐색
문제 자체는 단순히 배열을 정렬한 후 M번에 걸쳐서 해당 요소의 첫 위치를 찾아내면 되는 문제이다. N과 M이 작다면 그냥 O(N×M)인 indexOf()
로 해결할 수 있지만 N과 M이 각각 최대 20만이기 때문에 이 방법은 시간초과가 발생한다.
코틀린에서는 이진탐색을 수행하는 binarySearch()
메소드가 존재하지만 이 메소드는 찾고자 하는 값을 발견하면 가장 첫 위치가 아니라 이진 탐색중에 발견한 위치를 바로 반환하기 때문에 사용할 수 없다.
때문에 직접 이진탐색을 위한 메소드를 구현해야 하는데 이는 어렵지 않다. 기본으로 구현되어 있는 binarySearch()
메소드에서 값을 찾았을 때 바로 위치를 반환하지 않고 계속 이진탐색을 수행하도록 하면 된다.
마지막에 반환할 때 발견한 위치의 요소가 찾고자 하는 값과 같다면 발견한 위치를 반환하면 된다.(이 때, ArrayIndexOutOfBoundsException을 방지하기 위한 예외 처리를 해줘야 한다.) 그렇지 않은 경우에는 -1을 반환한다.
속도는 느리지만 Map을 사용하는 방법도 있다. 배열을 정렬한 후 배열을 순회하면서 Map에 요소를 key로, 위치를 value로 저장하면 된다. 이 때, 해당 key가 Map에 존재하지 않는 경우에만(= 해당 key의 value가 null
일 때만) value를 설정해주면 된다. 이후 Map에서 값을 꺼내면서 값이 없는 경우에는 -1을 출력하면 된다.
Code
이진 탐색
fun main() = with(System.`in`.bufferedReader()) { val bw = System.out.bufferedWriter() val (n, m) = readLine().split(' ').map { it.toInt() } val arr = IntArray(n) { readLine().toInt() }.sortedArray() repeat(m) { bw.write("${arr.binarySearch(readLine().toInt())}\n") } bw.close() } private fun IntArray.binarySearch(target: Int): Int { var start = 0 var end = size while (start < end) { val mid = (start + end) / 2 if (this[mid] >= target) end = mid else start = mid + 1 } return if (start < size && this[start] == target) start else -1 }
Map
fun main() = with(System.`in`.bufferedReader()) { val bw = System.out.bufferedWriter() val (n, m) = readLine().split(' ').map { it.toInt() } val map = IntArray(n) { readLine().toInt() }.sortedArray().run { HashMap<Int, Int>().apply { forEachIndexed { i, v -> get(v) ?: put(v, i) } } } repeat(m) { bw.write("${map[readLine().toInt()] ?: -1}\n") } bw.close() }
두 방법의 속도 차이

아래가 이진 탐색을 사용한 코드, 위가 Map을 사용한 코드이다. 확실히 이진탐색이 더 빠른 것을 볼 수 있다.
'Algorithm > BOJ' 카테고리의 다른 글
[Kotlin] 백준 27162 : Yacht Dice (0) | 2023.09.05 |
---|---|
[Kotlin] 백준 6568 : 귀도 반 로썸은 크리스마스날 심심하다고 파이썬을 만들었다 (0) | 2023.08.31 |
[Kotlin] 백준 1644 : 소수의 연속합 (0) | 2023.08.11 |
[Kotlin] 백준 12789 : 도키도키 간식드리미 (0) | 2023.08.09 |
[Kotlin] 백준 13305 : 주유소 (0) | 2023.07.27 |
댓글