[프로그래머스] Lv.2 오픈채팅방 JAVA 풀이
문제 Lv.2 오픈채팅방
: 오픈채팅방에서는 닉네임을 사용
누군가 들어오면 "[닉네임]님이 들어왔습니다." 라고 출력
누군가 나간다면 "[닉네임]님이 나갔습니다." 라고 출력
: 닉네임 변경 방법
- 채팅방 나가고 새로운 닉네임으로 다시 들어오기
- 채팅방에서 닉네임 변경하기
- 닉네임이 변경되면 기존 메시지의 닉네임도 전부 변경
- 닉네임 중복가능
- 닉네임을 변경한 기록이 담긴 문자열 배열 = record
- 모든 기록이 처리된 후 최종 출력 결과를 문자열 배열 행태로 return 한다
: < record >
- 1 ≤ record ≤ 100,000
- 모든 유저는 [유저 아이디]로 구분
- [유저 아이디] 사용자가 [닉네임]으로 채팅방에 입장 - "Enter [유저 아이디] [닉네임]" (ex. "Enter uid1234 Muzi")
- [유저 아이디] 사용자가 채팅방에서 퇴장 - "Leave [유저 아이디]" (ex. "Leave uid1234")
- [유저 아이디] 사용자가 닉네임을 [닉네임]으로 변경 - "Change [유저 아이디] [닉네임]" (ex. "Change uid1234 Muzi")
- 첫 단어는 Enter, Leave, Change 중 하나이다.
- 각 단어는 공백으로 구분되어 있으며, 알파벳 대문자, 소문자, 숫자로만 이루어져있다.
- 유저 아이디와 닉네임은 알파벳 대문자, 소문자를 구별한다.
- 유저 아이디와 닉네임의 길이는 1 이상 10 이하이다.
- 채팅방에서 나간 유저가 닉네임을 변경하는 등 잘못 된 입력은 주어지지 않는다.
: < 입출력 예시 >
- record : ["Enter uid1234 Muzi", "Enter uid4567 Prodo", "Leave uid1234"]
- result : ["Muzi 님이 들어왔습니다.", "Prodo님이 들어왔습니다.", "Muzi님이 나갔습니다."]
[문제 접근]
< String[] spt = record[i].split(" ") >
- 문자열 중 첫번째 값들 (Enter, Leave) 로 비교해서 출력하기
Change는 닉네임이 바뀔뿐 다시 출력하지는 않으니 무시한다 - 공백 단위로 문자를 끊기 위해서는 split(" ")이 필요할 듯
- 이때 중요한건 record 자체가 통으로 연결된 문자열이 아닌 배열이라는 것이다
그래서 index를 정해놓고 하나하나 들어가 문자열을 분해해야 한다
즉 record는 for문을 통해서 [i]라는 index를 달아주기
< Map<String, String>map = new HashMap<>() >
- id를 먼저 찾고 닉네임을 연결하는 모습이 마치 key값과 value값의 느낌같다
대신 record를 보면 Leave로 시작하는 문장은 닉네임이 없다
고로 record 길이가 3 (=상태, id, 닉네임)인 경우만 map에 value를 추가해줄 수 있다 - 같은 키 값에 여러 value라면 덮어씌워져 최근에 저장된 value만 살아남는다
< ArrayList<String> answer = new ArrayList<>() >
- 배열로 출력하라고 했는데 배열 크기 정하기가 귀찮아서 가변적인 ArrayList 설정
- 반환값이 ArrayList이므로 main 메서드 형태도 String[] 가 아닌 List<String>으로 변경
[코드]
import java.util.*;
class Solution {
public List<String> solution(String[] record) {
Map<String, String> map = new HashMap<>();
ArrayList<String> answer = new ArrayList<>();
for(int i = 0; i<record.length; i++){
String[] spt =record[i].split(" ");
if(spt.length == 3)
map.put(spt[1], spt[2]);
}
for(int i = 0; i<record.length; i++){
String[] spt =record[i].split(" ");
switch(spt[0]){
case "Enter":
answer.add(map.get(spt[1])+"님이 들어왔습니다.");
break;
case "Leave":
answer.add(map.get(spt[1])+"님이 나갔습니다.");
break;
}
}
return answer;
}
}
: public List<String> solution(String[] record) { 리턴값이 ArrayList이므로 형식 똑같이 맞춰주기
: Map<String, String> map = new HashMap<>(); id를 key로 삼아 닉네임을 value로 저장하는 map
ArrayList<String> answer = new ArrayList<>(); 출력할 배열
: for(int i = 0; i<record.length; i++){
String[] spt =record[i].split(" "); record의 i번째 문자를 공백 단위로 구분해서 spt 배열에 저장
if(spt.length == 3) 단, spt의 길이가 3일 경우에만 map에 값을 추가한다 (Leave를 예외로)
map.put(spt[1], spt[2]); key = spt[1] = id / value = spt[2] = 닉네임
}
: for(int i = 0; i<record.length; i++){ 위의 for문과 하나로 합치면 변경 전, 후 닉네임이 둘 다 떠서 따로 구분
String[] spt =record[i].split(" "); 한 번 더 써줘야 한다 아래에서 쓸거라
switch(spt[0]){ 0번째 문자로 비교
case "Enter":
answer.add(map.get(spt[1])+"님이 들어왔습니다."); spt[1] = key, value( = spt[2] = 닉네임)
break;
case "Leave":
answer.add(map.get(spt[1])+"님이 나갔습니다."); spt[1] = key, value( = spt[2] = 닉네임)
break;
}
}
: return answer; answer 배열 출력
[시간 복잡도]
for문을 2개 사용
for문 둘 다 record만큼 돌기 때문에 O(2N)
즉, 시간복잡도는 O(N) 이다
https://school.programmers.co.kr/learn/courses/30/lessons/42888
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
* 독학으로 익히는 코딩이라 틀린 것이 있을 수 있습니다. 오류가 있다면 댓글을 통해 알려주세요. 감사합니다. *