📍 달리기 경주
해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때 추월한 선수의 이름을 부릅니다.
선수들의 이름이 1등부터 현재 등수 순서대로 담긴 문자열 배열 players
와 해설진이 부른 이름을 담은 문자열 배열 callings
가 매개변수로 주어질 때, 경주가 끝났을 때 선수들의 이름을 1등부터 등수 순서대로 배열에 담아 return 하는 solution 함수를 완성해주세요.
players
의 길이 ≤ 50,000players[i]
는 i번째 선수의 이름을 의미합니다.players
의 원소들은 알파벳 소문자로만 이루어져 있습니다.players
에는 중복된 값이 들어가 있지 않습니다.players[i]
의 길이 ≤ 10callings
의 길이 ≤ 1,000,000callings
는 players
의 원소들로만 이루어져 있습니다.우선 제한사항을 신경쓰지 않고 풀어보았다.
{"선수이름": [불린 이름]}
형태의 Map을 생성*
를 사용하면 배열을 풀어서 넣을 수 있다.class Solution {
fun solution(players: Array<String>, callings: Array<String>): Array<String> {
var calls = callings.groupBy { it }
var p = mutableListOf<String>(*players)
calls.map { (name, called) ->
var i = players.indexOf(name)
var c = called.size
p.remove(name)
p.add(i-c, name)
}
return p.toTypedArray()
}
}
너도 나도 우리 모두 알 것이다. 이 코드는 썩었.. 아니 시간 초과가 발생한다. list는 포인터를 사용해 탐색을 하기 때문에 탐색 성능이 좋지 않다고 한다. 그 대신 앞과 뒤에 어떤 요소가 있는지 알고 있기 때문에 add(삽입할 위치, 값)
같은 삽입이나 삭제 작업을 쉽게 할 수 있다. 위의 풀이는 players라는 배열과 플레이어 리스트를 둘 다 탐색하는 코드이기 때문에 시간이 초과된다.
사실 감이 안잡혔다. 오케이 배열이 탐색이 빠르니까 배열을 사용해야지! 하고 생각하니 도대체 어떻게 배열로 구현해야하는 건지 너무 막막했다. 작성은 내가 했지만 사실 다른 사람들의 코드를 이거저거 조합해 풀이했다.
검색을 통해 HashMap을 사용하면 빠른 탐색이 가능하다는 정보를 얻게 되었다! 그래서 HashMap은 무엇인고 하니, MutableMap의 한 종류라고 한다. 배열은 인덱스를 통해 값을 찾아 시간 복잡도가 O(n)이지만, Map은 key를 통해 값을 찾기 때문에 시간 복잡도가 O(1)이다!
이제 나는 list보다 배열이, 배열보다 Map이 빠르다는 것을 안다. 선수들의 이름을 key로, 순위를 value로 갖는 Map을 사용해 풀이했다.
그런데 나는 이미 첫 번째 풀이에서 이름이 불린 횟수를 다룰 때 Map을 사용했다. Map을 사용했는데도 시간 초과가 발생한 것을 보니, 선수의 순위를 탐색할 때도 Map을 사용해야 하는가 보다.
class Solution {
fun solution(players: Array<String>, callings: Array<String>): Array<String> {
var p = players.indices.associateBy { players[it] }.toMutableMap()
callings.map { name ->
var originRank = p[name]!!
var frontName = players[originRank - 1]
// 실제 답이 되는 배열 수정
players[originRank] = frontName
players[originRank - 1] = name
// 변경된 순위 적용
p[name] = originRank - 1
p[frontName] = originRank
}
return players
}
}
사실 조금 억울한 게 있다. 여태 매개변수로 받은 배열을 수정할 수 없어서 항상 변수에 대입해 수정하곤 했는데, 세상에 이 문제는 그냥 수정이 되는 것이다! 나는 아예 다 안되는 건 줄 알았는데.. 아니었나보다..
믿어왔던 List에게 섭섭함을 느끼게 된 문제였다. 그래도 나에게 Map의 이점을 알려주었기 때문에 화해했다. 앞으로 시간 초과 발생하면 냅다 바로 Map을 꺼내들 것이다. 탐색용은 Map으로, 저장용은 배열이나 List를 사용해야겠다!