[프로그래머스] 오픈채팅방

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/42888

접근 방식

Map 구조를 이용하여, 키는 아이디, 밸류는 닉네임으로 관리한다.

입장과 닉네임 변경시에만, Map에서 해당 아이디를 가진 유저의 닉네임을 변경한다.

입장과 퇴장시에는 메시지를 출력해야 하기 때문에, 아이디를 기준으로 입/출력 문구를 생성해서 관리한다.

Map의 키와 일치하는 값을 밸류로 모두 변경한 뒤 리턴한다.

잘못된 접근

두 가지의 문제가 발생했다.

  1. 아이디가 test12, test123 이렇게 있을 경우, test12를 replace 하면 test123의 데이터도 변경되어 결과 값이 변형된다.
  2. replace 과정에서 이 중 for문이 사용되므로 (사용되지 않더라도 replace 연산) 시간 초과가 발생한다.

잘 된 접근

문자열을 생성은 단 한번만 이루어지는 것이 최선이다. 따라서 두 자료구조를 이용해서 입/퇴장과 아이디/닉네임을 관리할 수 있다.

  1. 먼저, 리스트를 이용해서 순서가 보장된 입/출력을 관리한다.
    이 과정에서 리스트에 String 객체 배열로 아이디와 메시지를 저장한다. ex) ["test12", "님이 들어왔습니다."]

  2. Map 구조를 이용한 닉네임 구조는 그대로 유지한다.

  3. 정답 만들기

    1. list 크기만큼 문자열 배열 초기화
    2. 현재 list에는 문자열 배열형태로 0번 인덱스에는 아이디, 1번 인덱스에는 문구가 저장되어있다. 따라서 0번 인덱스로 Map에서 닉네임을 가져와 1번 인덱스인 문구와 결합하여 문자열을 만들고, 이를 3-1의 문자열 배열에 저장한다.

결과

소스 코드

import java.util.*;

class Solution {
    public String[] solution(String[] record) {
        Map<String, String> map = new HashMap<>();
        List<String[]> list = new ArrayList<>();

        for(int i=0; i<record.length; i++){
            String[] r = record[i].split(" "); // 기록 분리
            // 입장
            if(r[0].equals("Enter")){
                list.add(new String[] {r[1], "님이 들어왔습니다."});
                map.put(r[1], r[2]); // 데이터 입력 or 수정
            }
            // 퇴장
            else if(r[0].equals("Leave")){
                list.add(new String[] {r[1], "님이 나갔습니다."});
            }else{
                map.put(r[1], r[2]); // 데이터 입력 or 수정
            }
        }

        // 아이디 > 닉네임 변환 및 문자열 생성
        String[] answer = new String[list.size()];
        for(int i=0; i<list.size(); i++){
            String[] tmp = list.get(i);
            answer[i] = map.get(tmp[0]) + tmp[1];
        }

        return answer;
    }
}