[프로그래머스] 오픈채팅방
문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/42888
접근 방식
Map 구조를 이용하여, 키는 아이디, 밸류는 닉네임으로 관리한다.
입장과 닉네임 변경시에만, Map에서 해당 아이디를 가진 유저의 닉네임을 변경한다.
입장과 퇴장시에는 메시지를 출력해야 하기 때문에, 아이디를 기준으로 입/출력 문구를 생성해서 관리한다.
Map의 키와 일치하는 값을 밸류로 모두 변경한 뒤 리턴한다.
잘못된 접근
두 가지의 문제가 발생했다.
- 아이디가 test12, test123 이렇게 있을 경우, test12를 replace 하면 test123의 데이터도 변경되어 결과 값이 변형된다.
- replace 과정에서 이 중 for문이 사용되므로 (사용되지 않더라도 replace 연산) 시간 초과가 발생한다.
잘 된 접근
문자열을 생성은 단 한번만 이루어지는 것이 최선이다. 따라서 두 자료구조를 이용해서 입/퇴장과 아이디/닉네임을 관리할 수 있다.
-
먼저, 리스트를 이용해서 순서가 보장된 입/출력을 관리한다.
이 과정에서 리스트에 String 객체 배열로 아이디와 메시지를 저장한다.ex) ["test12", "님이 들어왔습니다."]
-
Map 구조를 이용한 닉네임 구조는 그대로 유지한다.
-
정답 만들기
- list 크기만큼 문자열 배열 초기화
- 현재 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;
}
}