https://school.programmers.co.kr/learn/courses/30/lessons/17683
옛날에 풀려다가 문제를 이해를 못 해서 넘겼었던 문제이다.
오랜만에 다시 천천히 읽어보니 단순 구현문제였다.
핵심
요즘 문제를 풀 때 주석을 달고 분석을 시작하고 한다. 일단 내가 적은 주석이다.
// 우선 문자를 구분해줘야함 C, C# 등등 -> 중요포인트라고 생각되는건
// C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개가 있음 #은 다른 문자로 대체하느게 좋아보임
// A B C D E F G H I J K L
// A B C D E F G A# C# D# F# G# 이렇게 매칭하기
// 문자를 반복해서 길게 이어줘야함 ex) 14분동안 진행이면 7분짜리 노래 x 2
// contains로 찾으면 됨
// (추가) 플레이 타임인 긴 순서, 같다면 먼저 찾은 노래로
개인적으로 핵심은 #부분을 다른 문자로 대체하는 것이다.
정답 코드
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
class Solution {
static HashMap<Integer, String> matchingTimeAndTitle = new HashMap<>();
public String solution(String m, String[] musicInfos) {
for (String musicInfo : musicInfos) {
findMatchMusic(m, musicInfo);
}
Optional<Entry<Integer, String>> max = matchingTimeAndTitle
.entrySet()
.stream()
.max(Comparator.comparingInt(Entry::getKey));
return max.map(Map.Entry::getValue)
.orElse("(None)");
}
private void findMatchMusic(String m, String music) {
String[] musicInfo = music.split(",");
m = changeMusic(m);
String target = changeMusic(musicInfo[3]);
int runtime = findRuntime(musicInfo[0], musicInfo[1]);
StringBuilder totalMusic = new StringBuilder();
for (int i = 0; i < runtime; i++) {
totalMusic.append(target.charAt(i % target.length()));
}
if (isCorrectMatchingMusic(totalMusic, m, runtime)) {
matchingTimeAndTitle.put(runtime, musicInfo[2]);
}
}
private String changeMusic(String music) {
return music.replace("A#", "H")
.replace("C#", "I")
.replace("D#", "J")
.replace("F#", "K")
.replace("G#", "L");
}
private int findRuntime(String startTime, String endTime) {
String[] endTimeSplit = endTime.split(":");
String[] startTimeSplit = startTime.split(":");
int endHour = Integer.parseInt(endTimeSplit[0]);
int endMinute = Integer.parseInt(endTimeSplit[1]);
int startHour = Integer.parseInt(startTimeSplit[0]);
int startMinute = Integer.parseInt(startTimeSplit[1]);
int end = endHour * 60 + endMinute;
int start = startHour * 60 + startMinute;
return end - start;
}
private boolean isCorrectMatchingMusic(StringBuilder totalMusic, String m, int runtime) {
return totalMusic.toString().contains(m) && !matchingTimeAndTitle.containsKey(runtime);
}
}
해설
생각보다 단순한 구현문제였다.
우선 각 음악의 정보와 내가 들은 음악정보를 반복문을 통해 각각 비교를 한다.
findMatchMusic으로 들어가면 아까 말했듯이 #을 다른 문자로 대체하여 쉽게 풀 수 있도록 만들어준다.
이후 반복된 시간을 찾은 다음 그 음악을 런타임 시간 동안 반복하여 전부 송출된 음악을 찾는다.
만약 내가 들은 음악과 전체 음악이 같다면 matchingTimeAndTitle에 넣어준다.
여기서 중요한 점은 길이 같은 경우에는 이미 들어온 값을 사용해야 하기 때문에 업데이트하지 않는다.
전부 반복문을 통해 찾았다면 키값(런타임)이 가장 큰 값을 반환한다. 만약 없다면 -> 매칭이 없었음
요구대로 (None)을 반환한다.
배운 점
최근에 리트코드만 풀다가 오랜만에 프로그래머스가 풀고 싶어 져서 복귀했다.
요즘은 그냥 재미있어서 계속 푸는 느낌이 강하다.
주석에서 (추가)라고 쓴 부분이 있는데, 이 부분을 놓치고 풀어서 처음에 삽질을 좀 하였다.
자세히 읽으려 했음에도 잘 안 읽히는 부분이 있는 것 같다.
그래도 나름대로 빠르게 찾아서 해결할 수 있었다.
예전에도 이 문제를 풀려했었는데, 문제자체가 이해가 안 돼서 포기했었다.
그동안의 성장? 덕분인지 문제 해석도 잘되고 생각보다 쉽게 풀 수 있었다.
현재 300등을 돌파하였다.
알고리즘이 재미있어서 꾸준히 풀다 보니 순위가 높아지는 것 같다.
덕분에 논리적 사고력도 전에 비해 많이 늘었다는 생각도 든다.
순위가 높아지다 보니 랭킹을 높이는 재미도 생겼다.
그래서 현재 목표는 100등을 향해 달리는 것이다.
'PS > 알고리즘 문제풀이' 카테고리의 다른 글
[백준] 9328번 열쇠(java) (0) | 2023.08.09 |
---|---|
[백준] 13460번 구슬 탈출2(java) (0) | 2023.08.08 |
[LeetCode] 688 - Knight Probability in Chessboard(java) (0) | 2023.07.22 |
[LeetCode] 2024 - Maximize the Confusion of an Exam(java) (0) | 2023.07.07 |
[LeetCode] 209 - Minimum Size Subarray Sum(java) (0) | 2023.07.06 |