어려웠던 문제였다. 로직이 간단하지도 않고 마지막까지 방심하면 틀리는 문제였기 때문이다.
꼼꼼하게 생각하지 못한 탓인지 첫 풀이에는 테스트 케이스가 반 이상 틀렸고 한번 수정에 테스트 케이스를
1~2개씩 맞추기 시작해서 결국 전부 다 맞게 되었다. 다만 문제를 푸는데 시간이 너무 오래 걸렸다.
로직
일치하는 음악이 없을 때 바로 반환하기 위해 answer를 (None)으로 초기화한다.
musicinfos 배열을 순회하면서 탐색을 시작한다.
순차적으로 재생 시간을 구하는 메서드, 재생 시간에 맞춰 악보를 만드는 메서드, 조합을 검사하는 메서드를 호출한다.
첫 번째 메서드는 재생 시간을 분으로 변환해서 총 재생시간을 분으로 변환하고 시간을 반환한다.
두 번째 메서드는 재생 시간만큼 멜로디를 만들어 list에 저장한다. 여기서 #처리가 까다로운 편인데 나는 idx와 cnt 변수를 만들어서 다음 문자에 #을 만나면 추가하는 방법으로 풀이했다. 다른 분들 풀이를 보니 C# -> H처럼 #이 들어간 문자를 다른 문자로 치환하는 방법을 사용했다. 여기서 #을 적절하게 처리해야지 다음 단계가 쉬워진다.
세 번째 메서드는 idx부터 list의 사이즈만큼 반복해서 만들어진 조합을 m과 비교하는 것인데 처음에는 Stringbuilder의 사이즈를 m.length만큼만 설정하려고 했으나 m에 있는 #때문에 반복 횟수를 조절하기 어려워 그냥 조합을 전부 만들어서 비교했다. 조합이 m과 같으면 result 배열에 저장하고 만약 다음 탐색에서 조합이 같고 재생시간이 긴 조합을 찾는다면 그 값으로 업데이트한다. 재생시간이 같으면 먼저 입력한 순서대로 출력하라고 했으니 지나간다. musicinfos 배열의 순회가 끝나면 result 배열에서 answer로 값을 복사하고 반환한다. 만약 result 배열이 비어있다면 조건에 맞는 곡이 없다는 의미임으로 (None)을 반환하게 된다.
최종 코드
import java.util.*;
class Solution {
static String answer;
static String[] result;
public String solution(String m, String[] musicinfos) {
// answer None으로 초기화
answer = "(None)";
// 정답을 저장할 배열 선언 (재생시간, 제목)
result = new String[2];
// musicinfos 길이만큼 순회
for (int i = 0; i < musicinfos.length; i++) {
String[] temp = musicinfos[i].split(",");
// 플레이 타임
int time = playTime(temp);
// 재생 시간에 맞춰 악보 만들기
List<String> list = new ArrayList<>(make(temp, time));
// 조합 검사
combination(list, time, temp, m);
}
// result 배열에서 복사
if(result[1] != null) {
answer = result[1];
}
return answer;
}
// 재생시간을 계산하는 메서드
static int playTime(String[] temp) {
// 시간을 분으로 변환하여 시간 반환
int difHour = Integer.parseInt(temp[1].split(":")[0]) - Integer.parseInt(temp[0].split(":")[0]);
int difMinute = Integer.parseInt(temp[1].split(":")[1]) - Integer.parseInt(temp[0].split(":")[1]);
int time = 0;
if (difHour != 0) {
time += difHour * 60;
}
time += difMinute;
return time;
}
// 재생 시간에 맞춰 악보를 만드는 메서드
static List<String> make(String[] temp, int time) {
int cnt = 0;
int idx = 0;
List<String> list = new ArrayList<>();
while (cnt < time) {
// idx가 temp의 사이즈를 벗어나면 0으로 초기화
if (idx >= temp[3].length()) {
idx = 0;
}
// 다음 문자가 #이라면 #추가하여 list에 저장
if (idx + 1 < temp[3].length() && temp[3].charAt(idx + 1) == '#') {
list.add(temp[3].charAt(idx) + "#");
idx += 2;
cnt++;
continue;
}
list.add(String.valueOf(temp[3].charAt(idx++)));
cnt++;
}
return list;
}
// 만들어진 악보로 조합 만들기
static void combination(List<String> list, int time, String[] temp, String m) {
// idx부터 list의 크기만큼 문자열 조합을 생성하여 m과 같은지 비교
int idx = 0;
while (idx < list.size()) {
StringBuilder sb = new StringBuilder();
for (int i = idx; i < list.size(); i++) {
sb.append(list.get(i));
// 만들어진 조합이 m과 같으면
if (sb.toString().equals(m)) {
// result 배열이 비어있다면 (처음으로 m과 같은 조합 발견)
if(result[0] == null) {
result[0] = String.valueOf(time);
result[1] = temp[2];
continue;
}
// 문자열이 같고 재생시간이 길다면 result 배열 업데이트
if (time > Integer.parseInt(result[0])) {
result[0] = String.valueOf(time);
result[1] = temp[2];
}
}
}
idx++;
}
}
}
'코딩 테스트' 카테고리의 다른 글
(Java) 프로그래머스 - 정수 삼각형 (0) | 2022.09.29 |
---|---|
(Java) 프로그래머스 - 교점에 별 만들기 (0) | 2022.09.28 |
(Java) 프로그래머스 - 쿼드 압축 후 개수 세기 (0) | 2022.09.23 |
(Java) 프로그래머스 - 방문 길이 (1) | 2022.09.21 |
(Java) 프로그래머스 - n진수 게임 (0) | 2022.09.19 |