방금그곡
문제 요약
- 기억한 멜로디
m과 방송된 곡들의 정보(musicinfos)가 주어진다 - 각 곡은 시작·종료 시각만큼 처음부터 반복 재생된 것으로 간주한다
- 재생된 악보 안에
m이 그대로 들어있는 곡 중, 재생 시간이 가장 긴 곡의 제목을 찾는다 - 일치하는 곡이 없으면
"(None)"을 반환한다
문제 풀이
처음에는 악보 문자열을 그대로 이어붙이고 indexOf로 비교하면 될 줄 알았다.
하지만 이 방식은 #이 붙은 음에서 문제가 생긴다.
#이 붙은 음은 두 글자(C#처럼)로 표현되는데, 문자열을 그대로 두고 검색하면 C# 안에 있는 C까지 C로 잘못 걸릴 수 있다.
실제로 세 번째 예시에서 HELLO의 악보는 C#DEFGABC#DEFGAB인데, 여기서 기억한 멜로디 ABC를 그대로 찾으면 C# 뒤에 이어지는 DEFGAB와 우연히 겹쳐 잘못된 매칭이 생길 수 있다.
이 문제의 핵심은 샵이 붙은 음을 소문자 알파벳 하나로 치환해서 모든 음을 한 글자로 통일하는 것이다.
이렇게 바꾸면 음 하나가 항상 한 글자에 대응하므로 순수한 문자열 검색으로 안전하게 비교할 수 있다.
convert에서 다음 글자가#이면 현재 음을 소문자로 바꾸고 한 글자를 건너뛴다- 각 곡은 재생 시간만큼 악보를 반복해서 이어붙인 뒤, 그 안에 변환된
m이 포함되는지 확인한다 - 조건을 만족하는 곡 중 재생 시간이 가장 긴 곡을 갱신해 나간다
최종 코드
import java.util.*;
class Solution {
public int toMin(String time){
int h = Integer.parseInt(time.substring(0,2));
int m = Integer.parseInt(time.substring(3));
return h*60+m;
}
public String convert(String code) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < code.length(); i++) {
char now = code.charAt(i);
// 다음 글자가 #이면 현재 음을 소문자 한 글자로 합쳐서 처리
if (i + 1 < code.length() && code.charAt(i + 1) == '#') {
result.append(Character.toLowerCase(now));
i++;
} else {
result.append(now);
}
}
return result.toString();
}
public String solution(String m, String[] musicinfos) {
int max = -1;
String answer = "(None)";
m = convert(m);
for(int i=0;i<musicinfos.length;i++){
StringTokenizer st = new StringTokenizer(musicinfos[i], ",");
int start = toMin(st.nextToken());
int end = toMin(st.nextToken());
String name = st.nextToken();
String c = convert(st.nextToken());
int time = end - start;
StringBuilder code = new StringBuilder();
// 재생 시간만큼 악보를 처음부터 반복해서 이어붙인다
for(int j=0;j<time;j++){
code.append(c.charAt(j%c.length()));
}
if(code.indexOf(m) != -1 && time > max){
max = time;
answer = name;
}
}
return answer;
}
}함께 읽으면 좋은 글
택배상자
order 배열은 택배 기사님이 원하는 상자 적재 순서다 기존 컨테이너 벨트는 1번부터 순서대로만 꺼낼 수 있다 보조 벨트는 스택처럼 마지막에 넣은 것부터 꺼낼 수 있다 원하는 순서대로 최대한 실을 수 있는 상자 개수를 구하는 문제다 처음에는 기존 벨트를 실제 리스트로 만들어…
롤케이크 자르기
topping 배열은 롤케이크에 일렬로 올라간 토핑 번호다 한 지점을 잘라 두 조각으로 나눴을 때, 양쪽 토핑 종류 수가 같아야 공평하게 나눈 것이다 공평하게 자를 수 있는 방법의 수를 구하는 문제다 처음에는 자르는 위치마다 왼쪽과 오른쪽 배열을 나눠서 각각 서로 다른 토핑…
할인 행사
want, number 배열로 정현이가 원하는 제품과 수량을 표현한다 discount 배열은 XYZ 마트가 매일 할인하는 제품 목록이다 연속된 10일 동안 할인 제품 종류와 수량이 want, number와 정확히 일치해야 회원가입할 수 있다 그런 시작일이 총 몇 번 있는지…
숫자 변환하기
자연수 x를 y로 바꾸는 데 x+n, x2, x3 세 가지 연산을 쓸 수 있다 x를 y로 바꾸는 최소 연산 횟수를 구하는 문제다 만들 수 없으면 -1을 반환한다 처음에는 x에서 시작해서 세 가지 연산을 재귀적으로 다 시도해보고 y에 도달하는 경로 중 가장 짧은 걸 고르면…