일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 2206번
- 클린코드
- Spring
- BOJ
- 1043번
- 2166번
- springboot
- 자바의 정석
- Dxerr.h
- 프로그래머스
- DxTrace
- 백준
- 냄새와 휴리스틱
- 코딩 테스트
- 17장
- java
- Adapater Pattern
- Design Patterns
- 가장 긴 증가하는 부분 수열2
- programmers
- 10830번
- 1300번
- 11286번
- 11758번
- java의 정석
- SerialDate 리펙터링
- 9장
- 코딩테스트
- Design Pattern
- 2156번
- Today
- Total
Don't give up!
[프로그래머스] 오픈채팅방(java) 본문
코딩테스트 연습 - 오픈채팅방 | 프로그래머스 (programmers.co.kr)
어떻게 생각하고 문제를 풀었는가?
입력 받는 문자열들은 모두 "[행동] [유저아이디]" 또는 "[행동] [유저아이디] [닉네임]"으로 이루어져 있습니다.
가장 마지막에 입력된 닉네임으로 메시지에 출력되기 때문에 유저아이디 - 닉네임으로 먼저 저장을 하는 작업을 수행한 후 행동에 따른 메시지를 출력하는 것으로 문제를 해결할 수 있다고 생각하였습니다.
코드
import java.util.Map;
import java.util.HashMap;
import java.util.Stack;
class Solution {
public String[] solution(String[] record) {
Map<String, String> nickname = new HashMap<>();
String[] words = new String[3];
for(String log : record){
words = log.split("\\s");
if(!words[0].equals("Leave")){
nickname.put(words[1],words[2]);
}
}
Stack<String> answer = new Stack<>();
for(int i=0; i<record.length; i++){
words = record[i].split("\\s");
if(words[0].equals("Enter")){
answer.push(nickname.get(words[1]) + "님이 들어왔습니다.");
}else if(words[0].equals("Leave")){
answer.push(nickname.get(words[1]) + "님이 나갔습니다.");
}
}
return answer.toArray(new String[answer.size()]);
}
}
설계를 바탕으로 코드를 작성하였습니다.
String의 split함수에 공백문자를 의미하는 정규표현식을 사용하여 유저아이디와 닉네임을 쉽게 가져올 수 있었습니다.
닉네임 변경은 메시지에 출력되지 않습니다. 따라서 Change의 행동을 출력에 포함시키지 않기 위해 stack을 활용하여 출력되어야 할 메시지들만을 저장한 후 toArray함수로 String 배열이 반환되도록 하였습니다.
테스트를 통과하고 난 후 다양한 출력메시지가 변경되어도 쉽게 적용될 수 있도록 코드를 개선해보고자 하였습니다.
개선
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
class Solution {
private final String FORMAT_ENTER = "%s님이 들어왔습니다.";
private final String FORMAT_LEAVE = "%s님이 나갔습니다.";
public String[] solution(String[] record) {
Map<String, String> nickname = new HashMap<>();
String[] words = new String[3];
for(String log : record){
words = log.split("\\s");
if(!words[0].equals("Leave")){
nickname.put(words[1],words[2]);
}
}
ArrayList<String> answer = new ArrsyList<>();
for(int i=0; i<record.length; i++){
words = record[i].split("\\s");
if(words[0].equals("Enter")){
answer.add(String.format(FORMAT_ENTER, nickname.get(words[1])));
}else if(words[0].equals("Leave")){
answer.add(String.format(FORMAT_LEAVE, nickname.get(words[1])));
}
}
return answer.toArray(new String[answer.size()]);
}
}
java String에서는 format함수를 제공합니다.
문자열의 형식을 저장하고 입력값을 형식에 적용한 문자열을 리턴함으로서 메시지의 형식이 변경되어도 미리 선언해둔 출력 형식만 변경하면 쉽게 이를 적용할 수 있습니다.
결과 메시지들을 담을 자료구조에 있어서도 Vector를 상속받는 Stack보다 ArrayList가 더 효율적이라고 판단하여 자료구조를 변경하였습니다.
Vector vs ArrayList
Vector와 ArrayList는 모두 AbstrackList를 상속받아 구현된 클래스입니다.
배열로 구현되어 있어 인덱스를 이용한 빠른 값 찾기가 가능하고 자동으로 메모리 공간을 늘려주는 작업을 수행합니다.(Vector는 크기를 2배, ArrayList는 1.5배로 증가)
그러나 Vector와 ArrayList는 동기화에 있어 큰 차이를 가지고 있습니다.
Vector는 동기화가 되어 있으나 ArrayList는 동기화가 되어있지 않습니다.
Vector는 한번에 하나의 스레드만 접근할 수 있고 ArrayList를 그렇지 않기 때문에 단일 스레드 작업에 대해서 ArrayList가 조금 더 빠른 속도를 보인다고 할 수 있겠습니다.
'Coding Test > Programmers' 카테고리의 다른 글
[프로그래머스] 타겟 넘버(java) (0) | 2021.05.06 |
---|---|
[프로그래머스] 큰 수 만들기(java) (0) | 2021.05.03 |
[프로그래머스] 가장 큰 수(java) (0) | 2021.05.02 |