https://school.programmers.co.kr/learn/courses/30/lessons/17684
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
코딩테스트 연습 | 프로그래머스 스쿨
개발자 취업의 필수 관문 코딩테스트를 철저하게 연습하고 대비할 수 있는 문제를 총망라! 프로그래머스에서 선발한 문제로 유형을 파악하고 실력을 업그레이드해 보세요!
school.programmers.co.kr
<2018년도 카카오 블라인드 채용 기출 [3차]>
위의 문제를 이전에 풀어봤을 땐 5일씩 붙잡고 풀었던 기억이 난다.
여러 가지 노하우가 쌓인 지금 HashMap과 StringBuilder를 사용해서 다시 풀어봤다.
구현 착안

(최적화 전 -> 최적화 후)
ArrayList -> HashMap 사용
String + 더하기 연산 -> StringBuilder 사용
최적화 하기 전 코드
import java.util.ArrayList;
class P압축 {
public ArrayList<Integer> solution(String msg) {
// TOBEORNOTTOBEORTOBEORNOT
/*
T[20] O / TO : 27
O[15] B / BO : 28
B[2] E / BE : 29
E[5] O / EO : 30
O[15] R / OR : 31
R[18] N / RN : 32
N[14] O / NO : 33
O[15] T / OT : 34
T[20] T / TT : 35
TO[27] B / TOB : 36
BE[29] O / BEO : 37
OR[31] T / ORT : 38
TOB[36] E / TOBE : 39
EO[30] R / EOR : 40
RN[32] O / RNO : 41
OT[34]
*/
// 문자열을 압축한 후의 사전 색인 번호
ArrayList<Integer> answer = new ArrayList<>();
// 사전
ArrayList<String> alphabet = new ArrayList<>();
// 사전 초기화
for(int i = 0; i < 26; i++) {
alphabet.add(Character.toString((char) (i + 65)));
}
int remain = 0;
for(int i = 0; i < msg.length(); i++) {
String w = "";
String str = "";
// 현재 인덱스에 해당하는 문자를 한 글자를 str 담는다.
str += msg.charAt(i);
for(int j = i + 1; j < msg.length(); j++) {
// str을 w에 저장한다.
w = str;
// str에 그 다음 한 글자를 더 붙인다.
str += msg.charAt(j);
if(!alphabet.contains(str)) { // str이 새로운 단어라면
alphabet.add(str); // 사전에 str을 등록한다.
/* 중요 */
if(w.length() > 1) i += w.length() - 1; // w이 두 글자 이상이면 i 인덱스가 (글자 길이 - 1)에 가게 한다.
remain = i; // i 인덱스를 remain에 잠시 저장한다. (마지막으로 처리되지 않은 글자)
answer.add(alphabet.indexOf(w) + 1); // 사전에서 w의 색인 번호를 찾아 정답 배열에 담는다.
break;
}
}
}
String lastStr = "";
// 입력이 길이가 1인 문자열일 때
if(msg.length() == 1) {
answer.add(1);
} else {
// 길이가 2 이상의 문자열은 위의 로직을 거치고 옴
// 마지막 남은 글자 answer에 추가
for(int i = remain + 1; i < msg.length(); i++) {
lastStr += msg.charAt(i);
}
// 새로운 단어는 위의 로직에서 모두 등록을 마쳤기 때문에
// lastStr은 무조건 사전에 등록된 단어이다.
answer.add(alphabet.indexOf(lastStr) + 1);
}
return answer;
}
public static void main(String[] args) {
P압축 p = new P압축();
System.out.println(p.solution("TOBEORNOTTOBEORTOBEORNOT"));
}
}
최적화 후 코드
import java.util.ArrayList;
import java.util.HashMap;
class P압축_최적화 {
public ArrayList<Integer> solution(String msg) {
// 문자열을 압축한 후의 사전 색인 번호
ArrayList<Integer> answer = new ArrayList<>();
// 사전
HashMap<String, Integer> alphabet = new HashMap<>();
// 사전 초기화
for(int i = 0; i < 26; i++) {
alphabet.put(Character.toString((char) (i + 65)), i + 1);
}
int remain = 0;
for(int i = 0; i < msg.length(); i++) {
StringBuilder w = new StringBuilder();
StringBuilder str = new StringBuilder();
// 현재 인덱스에 해당하는 문자를 한 글자를 str 담는다.
str.append(msg.charAt(i));
for(int j = i + 1; j < msg.length(); j++) {
// str을 w에 저장한다.
w.setLength(0);
w.append(str);
// str에 그 다음 한 글자를 더 붙인다.
str.append(msg.charAt(j));
if (!alphabet.containsKey(str.toString())) { // str이 새로운 단어라면
alphabet.put(str.toString(), alphabet.size() + 1); // 사전에 str을 등록한다.
if(w.length() > 1) i += w.length() - 1; // w이 두 글자 이상이면 i 인덱스가 (글자 길이 - 1)에 가게 한다.
remain = i; // i 인덱스를 remain에 잠시 저장한다. (마지막으로 처리되지 않은 글자)
answer.add(alphabet.get(w.toString())); // 사전에서 w의 색인 번호를 찾아 정답 배열에 담는다.
break;
}
}
}
// 입력이 길이가 1인 문자열일 때
if(msg.length() == 1) {
answer.add(1);
}
// 마지막 글자 처리
if (remain < msg.length() - 1) {
String lastStr = msg.substring(remain + 1);
answer.add(alphabet.get(lastStr));
}
return answer;
}
public static void main(String[] args) {
P압축_최적화 p = new P압축_최적화();
System.out.println(p.solution("TOBEORNOTTOBEORTOBEORNOT"));
}
}
w.setLength(0);
w.append(str);
여기서 StringBuilder는 대입 연산이 되지 않기 때문에 setLength(0)로 StringBuilder 변수를 초기화하고 append 해줘야 한다.
제출 결과


문제 풀이 최적화 결론
- 문자열 조작 시 문자열을 더하는 것 보다 StringBuilder를 사용하는 편이 좋다.
- 기존의 alphabet.contains(str)로 중복 확인을 하면 O(n) 시간이 걸릴 수 있다. ArrayList 대신 HashMap을 사용하여 O(1)의 시간복잡도로 조회할 수 있다.
최적화 후(HashMap, StringBuilder)가 최적화 하기 전(ArrayList에서 조회, String + 더하기 연산)보다 약 1/10배의 시간을 줄여준 것을 확인할 수 있었다.
'Algorithm' 카테고리의 다른 글
[Programmers] 등굣길 Java (1) | 2023.11.28 |
---|---|
[Programmers] 가장 먼 노드 Java (0) | 2023.11.22 |
[Programmers] 단속 카메라 Java (0) | 2023.11.22 |
[SWEA] 1859. 백만 장자 프로젝트 D2 Java (0) | 2023.10.27 |
[Programmers] 동적 계획법 > 정수 삼각형 (Java) (0) | 2023.10.13 |