안녕하세요. 오늘은 프로그래머스의 방금그곡 문제를 풀어보겠습니다. 이 문제는 2018 KAKAO BLIND RECRUITMENT에 출제되었습니다.
https://programmers.co.kr/learn/courses/30/lessons/17683
문제 구현에 있어 C와 C#처럼 #이 붙은 음을 구분하는 것이 가장 까다로웠습니다. for문을 돌 때 다음 index의 string이 "#"이면 해당 index의 문자를 소문자로 치환하여 저장하는 방식으로 이를 해결하였습니다.
LinkedHashMap을 사용하여 순서를 저장하였습니다. LinkedHashMap의 key는 음표이고, value에는 제목을 저장하였습니다.
import java.text.*;
import java.util.*;
class Solution {
public String solution(String m, String[] musicinfos) throws ParseException {
String answer = "";
//key: 음표, value: 제목
LinkedHashMap<String, String> map = new LinkedHashMap<>();
SimpleDateFormat dateFormat = new SimpleDateFormat("mm:ss");
for (String str : musicinfos) {
//music[0] = 시작시간, music[1] = 끝시간
//music[2] = 제목, music[3] = 음표
String[] music = str.split(",");
Date start = dateFormat.parse(music[0]);
Date end = dateFormat.parse(music[1]);
int diff = (int) (end.getTime() - start.getTime()) / 1000;
StringBuilder sb = new StringBuilder();
int idx = 0;
String[] lyrics = music[3].split("");
for (int t = 0; t < diff; t++) {
//lyrics배열을 모두 돌면 배열의 처음으로 다시 이동
if(idx == lyrics.length) idx = 0;
if(idx < lyrics.length - 1) {
//다음 문자가 #이면 소문자로 저장
if("#".equals(lyrics[idx+1])) {
sb.append(lyrics[idx].toLowerCase());
sb.append(lyrics[idx+1]);
idx++;
} else {
sb.append(lyrics[idx]);
}
} else {
sb.append(lyrics[idx]);
}
idx++;
}
map.put(sb.toString(), music[2]);
}
//주어진 m도 #이 붙은 경우 소문자로 치환하여야 한다
StringBuilder makeM = new StringBuilder();
for (int i = 0; i < m.length(); i++) {
if(i < m.length()-1) {
if('#' == m.charAt(i+1)) {
makeM.append((char) (m.charAt(i)+32));
} else {
makeM.append(m.charAt(i));
}
} else {
makeM.append(m.charAt(i));
}
}
m = makeM.toString();
ArrayList<String> keyList = new ArrayList<>(map.keySet());
int idx = 0;
for(int i = 0; i < keyList.size(); i++) {
String key = keyList.get(i);
if(key.contains(m)) {
if("".equals(answer)) {
answer = map.get(key);
idx = i;
} else {
int pastLyricsLen = keyList.get(idx).length();
int nowLyricsLen = key.length();
if(nowLyricsLen > pastLyricsLen) {
answer = map.get(key);
idx = i;
}
}
}
}
if("".equals(answer)) answer = "(None)";
return answer;
}
}
처음엔 LinkedHashMap이 아닌 그냥 HashMap으로 문제를 풀었었다. 그랬더니 28번 테스트케이스에서 자꾸 실패가 떨어졌다. 이유는 HashMap에 있었다.
HashMap은 순서를 저장하지 않는다. 순서를 저장하기 위해서는 LinkedHashMap을 사용해야 한다.
문제에서 주어진 제약사항 중 "재생된 시간의 길이가 같으면 먼저 나온 곡이 answer다" 를 지키기 위해서는 순서를 저장해야 한다.
LinkedHashMap을 사용하니 문제없이 다 맞았다.😆
😆