1️⃣ 문제

제한사항

  • record는 다음과 같은 문자열이 담긴 배열이며, 길이는 1 이상 100,000 이하이다.
  • 다음은 record에 담긴 문자열에 대한 설명이다.
    • 모든 유저는 [유저 아이디]로 구분한다.
    • [유저 아이디] 사용자가 [닉네임]으로 채팅방에 입장 - “Enter [유저 아이디] [닉네임]” (ex. “Enter uid1234 Muzi”)
    • [유저 아이디] 사용자가 채팅방에서 퇴장 - “Leave [유저 아이디]” (ex. “Leave uid1234”)
    • [유저 아이디] 사용자가 닉네임을 [닉네임]으로 변경 - “Change [유저 아이디] [닉네임]” (ex. “Change uid1234 Muzi”)
    • 첫 단어는 Enter, Leave, Change 중 하나이다.
    • 각 단어는 공백으로 구분되어 있으며, 알파벳 대문자, 소문자, 숫자로만 이루어져있다.
    • 유저 아이디와 닉네임은 알파벳 대문자, 소문자를 구별한다.
    • 유저 아이디와 닉네임의 길이는 1 이상 10 이하이다.
    • 채팅방에서 나간 유저가 닉네임을 변경하는 등 잘못 된 입력은 주어지지 않는다.

입출력 예

record result
["Enter uid1234 Muzi", "Enter uid4567 Prodo","Leave uid1234","Enter uid1234 Prodo","Change uid4567 Ryan"] ["Prodo님이 들어왔습니다.", "Ryan님이 들어왔습니다.", "Prodo님이 나갔습니다.", "Prodo님이 들어왔습니다."]

2️⃣ 풀이 방법

처음에는 userInfo를 uid와 nickname이 들어간 struct를 만들어 struct 배열을 사용하였는데, 이때 Enter 또는 Change 시 이미 존재하는 user인지 확인하려면 배열에 대하여 .map() 또는 .filter()를 돌려서 확인해야 하기 때문에 O(n)이 더 걸려 몇 개의 테케에 시간 초과가 떴다.

그래서 userInfo를 딕셔너리로 바꿔주면서 바로 key값에 대해 update해줌으로써 시간초과를 해결하였다.

3️⃣ 코드

import Foundation

enum ChatInfo {
    case Enter(String)
    case Leave(String)
    
    var result: String {
        switch self {
        case .Enter(let uid):
            return "\(userInfo[uid]!)님이 들어왔습니다."
        case .Leave(let uid):
            return "\(userInfo[uid]!)님이 나갔습니다."
        }
    }
}

var chatInfo: [ChatInfo] = []       // 채팅 정보
var userInfo: [String: String] = [:]        // 유저 정보 [uid: nickname]

func solution(_ record:[String]) -> [String] {
    var answer: [String] = []
    
    // 1. record에 따른 채팅 정보와 유저 정보 담기
    record.forEach() {
        var strRecord = $0.split(separator: " ").map { String($0) }
        let command = strRecord.first!
        strRecord.removeFirst()
        switch command {
        case "Enter":
            let info = strRecord
            userInfo.updateValue(info.last!, forKey: info.first!)
            chatInfo.append(.Enter(info.first!))
        case "Leave":
            let uid = strRecord.last!
            chatInfo.append(.Leave(uid))
        case "Change":
            let info = strRecord
            userInfo.updateValue(info.last!, forKey: info.first!)
        default:
            break
        }
    }
    
    // 2. enum case에 따른 result 담아주기
    chatInfo.forEach() {
        answer.append($0.result)
    }
    
    return answer
}