[프로그래머스(Programmers)] 2018 KAKAO BLIND RECRUITMENT:: [3차] 방금그곡 (java)

1
post-thumbnail

안녕하세요. 오늘은 프로그래머스의 방금그곡 문제를 풀어보겠습니다. 이 문제는 2018 KAKAO BLIND RECRUITMENT에 출제되었습니다.


문제 링크

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

문제 설명

✔ C와 C#을 구분하는 방법 : C#은 소문자로 저장

문제 구현에 있어 C와 C#처럼 #이 붙은 음을 구분하는 것이 가장 까다로웠습니다. for문을 돌 때 다음 index의 string이 "#"이면 해당 index의 문자를 소문자로 치환하여 저장하는 방식으로 이를 해결하였습니다.

✔ LinkedHashMap 사용

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;
    }
}

느낀점

✔ HashMap과 LinkedHashMap의 차이

처음엔 LinkedHashMap이 아닌 그냥 HashMap으로 문제를 풀었었다. 그랬더니 28번 테스트케이스에서 자꾸 실패가 떨어졌다. 이유는 HashMap에 있었다.
HashMap은 순서를 저장하지 않는다. 순서를 저장하기 위해서는 LinkedHashMap을 사용해야 한다.
문제에서 주어진 제약사항 중 "재생된 시간의 길이가 같으면 먼저 나온 곡이 answer다" 를 지키기 위해서는 순서를 저장해야 한다.

LinkedHashMap을 사용하니 문제없이 다 맞았다.😆


[참고한 곳]
https://programmers.co.kr/questions/18255

1개의 댓글

comment-user-thumbnail
2021년 10월 16일

😆

답글 달기