알고리즘/PS - 프로그래머스

[프로그래머스 - Java] [3차] 방금그곡

excited-hyun 2021. 8. 5. 18:06
반응형

https://programmers.co.kr/learn/courses/30/lessons/17683

 

코딩테스트 연습 - [3차] 방금그곡

방금그곡 라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금그곡' 서비스를 이용하곤 한다. 방금그곡에서는 TV,

programmers.co.kr

 

풀이

이 문제는 재생시간을 계산해서 그 시간에 맞는 전체 악보를 생성하는 것이 중요한 문제입니다.

저는 악보 생성에서 삽질을 너무 했습니다ㅠㅠ

 

제가 이용한 알고리즘은 다음과 같습니다.

  1. 시작시간, 종료시간을 모두 분 단위로 변환해 재생시간 구함
  2. 재생시간에 맞게 재생되는 전체 악보 생성 (# 을 고려해서 몇분짜리 악보인지 구해야함)
  3. 전체 악보에서 문자열 m이 등장하는 위치들을 모두 찾아서 저장해둠
  4. 각각의 등장하는 위치들에 대해서 m이 등장한 후에 '#'이 이어지는 경우는 동일한 것이 등장한다고 볼 수 없음
  5. 등장하는 것을 찾은 경우 <Key : 재생시간, Value:제목>으로 HashMap을 생성 (이때 재생시간이 같은 경우 먼저 입력된 음악 제목이 답이기 때문에 저는 HashMap에 중복여부를 확인하기 귀찮아서 그냥 musicinfos를 뒤부터 탐색하고 앞으로 가면서 같은 재생시간이 있는 경우 업데이트 될 수 있도록하여 결국 앞값이 남게 구현했습니다.)
  6. 모든 musicinfos 탐색 후 재생시간 가장 큰 값을 찾음. HashMap이 빈 경우 answer = "(None)"

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


class Solution {
    public String solution(String m, String[] musicinfos) {
        String answer = "";
        Map<Integer, String> map1 = new HashMap<>();
        int size = musicinfos.length;
        
        //재생시간 동일한 경우 먼저 입력된 제목을 답으로 하기 위해 musicinfos를 뒤부터 탐색
        for(int j=size-1; j>=0; j--){
            String data = musicinfos[j];
            ArrayList<Integer> idxList = new ArrayList<Integer> ();    //등장위치
            String[] array = data.split(",");    //시작시간, 끝시간, 제목, 악보
            
            //시간 계산
            String[] s_time = array[0].split(":");
            String[] e_time = array[1].split(":");
            //분으로 변환
            int s_hour = Integer.parseInt(s_time[0]);
            int s_min = Integer.parseInt(s_time[1]);
            int e_hour = Integer.parseInt(e_time[0]);
            int e_min = Integer.parseInt(e_time[1]);
            
            s_min = s_min+s_hour*60;
            e_min = e_min+e_hour*60;
            int total_time = e_min - s_min;
            
            //#개수 count
            int cnt=0;
            for(int i=0; i<array[3].length(); i++) {
                if(array[3].charAt(i)=='#') {
                    cnt++;
                }
            }
            String sheet = "";
            int play_time = total_time;
            int play_len = array[3].length()-cnt;
            //재생시간이 악보 길이보다 긴 경우
            while(play_time >= play_len){
                sheet += array[3];
                play_time -= play_len;
            }
            
            //위의 처리 후 남은 재생시간이 있는 경우
            int end_idx=-1;
            if(play_time < play_len){
                for(int i=0; i<array[3].length(); i++){
                    
                    sheet+=array[3].charAt(i);
                    if(i == array[3].length()-1)
                        continue;
                    //다음꺼가 #인 경우 추가
                    if(array[3].charAt(i+1) == '#'){
                        sheet+=array[3].charAt(i+1);
                        i++;
                    }
                    
                    play_time--;
                    if(play_time < 0){
                        end_idx = i;
                        break;
                    }
                }
            }
            if(end_idx!=-1 && end_idx<array[3].length()-1){
                if(array[3].charAt(end_idx+1) == '#')
                    sheet+=array[3].charAt(end_idx+1);
            }
            
            //등장위치 모두 찾음
            int idx = sheet.indexOf(m);
            while(idx != -1){
                idxList.add(idx); 
                idx = sheet.indexOf(m, idx+m.length());
            }
            
            if(idxList.size() == 0)
                continue;
            
            //등장 안함.
            int sw = 0;
            //등장하는데, 뒤에 #이 붙는지 확인
            for(int i=0; i<idxList.size(); i++){
                int check = idxList.get(i)+m.length();
                
                if(check >= sheet.length())
                    break;
                if(sheet.charAt(check)!='#'){
                    sw = 1;
                    break;
                }
            }
            if(sw == 0)
                continue;
            
            //추가
            map1.put(total_time, array[2]);
            
        }
        //Map 확인
        Set<Map.Entry<Integer, String>> entries = map1.entrySet();
        int time = 0;
        for(Map.Entry<Integer,String> tempEntry: entries) {
            if(time < tempEntry.getKey()){
                time = tempEntry.getKey();
                answer = tempEntry.getValue();
            }
        }
        
        //Map이 비었던 경우는 time이 그대로 0으로 남게됨.
        if(time == 0)
            answer = "(None)";
        
        return answer;
    }
}
728x90
반응형