이 문제를 보면 중간에 바뀔 수 있는 닉네임을 계속 바꾸어가며 저장해야 합니다. 닉네임은 uid와 1:1로 연결되어 있으므로 Hash Table (dictionary)를 사용하면 O(1)로 접근 & 수정이 가능합니다.
닉네임을 Hash Table에 저장해야 하는 이벤트는 2가지입니다. 처음에 채팅방에 입장했을 때 (닉네임을 바꾸고 재입장을 하는 경우 포함)와 중간에 닉네임을 바꾸는 경우입니다.
구글링을 해보니 닉네임을 바꾸는 이벤트는 record의 문자열을 .split()했을 때 길이가 3이라는 점을 이용해서 일단 닉네임부터 dictionary에 모두 업데이트하고나서 다시 반복문을 돌아서 Enter, Leave를 처리하는 풀이도 있더군요.
저는 별도의 enum을 이용해서 enter와 uid를 함께 저장하는 방법을 사용해봤습니다. 근본적인 원리는 다른 풀이들과 동일합니다.
import Foundation
// 입장 or 퇴장을 uid와 함께 저장하기 위한 enum
enum Event {
case enter(uid: String)
case leave(uid: String)
}
func solution(_ record:[String]) -> [String] {
// nickname을 저장하기 위한 hash table
var dict = [String:String]()
// enter와 leave를 순서대로 저장하는 배열
var events = [Event]()
// 리턴할 문자열들을 담는 배열
var messages = [String]()
for r in record {
// 띄어 쓰기 기준으로 명령어를 array로 바꾼다.
let commend = r.split(separator: " ").map { String($0) }
// 입장과 퇴장은 uid와 함께 Event 배열에 저장하고
if commend[0] == "Enter" {
let uid = commend[1]
events.append(.enter(uid: uid))
dict[uid] = commend[2] //👉 enter의 경우 nickname도 같이 저장한다.
} else if commend[0] == "Leave" {
events.append(.leave(uid: commend[1]))
// change의 경우 dict에 새로운 닉네임을 업데이트한다.
} else {
dict[commend[1]] = commend[2]
}
}
// 입장, 퇴장을 순서대로 메시지를 작성하는데 닉네임은 uid를 통해 dict에서 찾는다.
for event in events {
switch event {
case .enter(let uid):
messages.append("\(dict[uid]!)님이 들어왔습니다.")
case .leave(let uid):
messages.append("\(dict[uid]!)님이 나갔습니다.")
}
}
return messages
}