프로그래머스 - 베스트 앨범 (JAVA)

2026. 4. 23. 02:23·CS/코딩테스트

프로그래머스 베스트 앨범 풀이 과정
해시 카테고리 문제인데, 정렬 기준이 여러 개라 꽤 헤맸다.
총 3번의 제출 끝에 통과


1트 (오답)

→ 장르별 총 스트리밍 횟수를 genMap에 저장하고, TreeMap의 Key 기준 역순 정렬로 장르 순서를 정하려 했다.
→ 각 곡의 인덱스는 playIdx에 plays[i] → i 형태로 저장했다.

import java.util.*;
// 음악 클래스
class Music implements Comparable<Music> {
    String genre;
    int play;

    public Music(String genre, int play) {
        this.genre = genre;
        this.play = play;
    }

    @Override
    public int compareTo(Music m) {
        return m.play - this.play;
    }
}
class Solution {
    public int[] solution(String[] genres, int[] plays) {
        Map<String, Integer> genMap = new HashMap<>(); // 장르별 스트리밍 횟수 저장
        Map<Integer, Integer> playIdx = new HashMap<>(); // 스트리밍 횟수 인덱스 저장
        List<Music> playlist = new ArrayList<>(); // 곡별 스트리밍 횟수 저장

        for(int i=0; i<plays.length; i++) {
            genMap.put(genres[i], genMap.getOrDefault(genres[i],0) + plays[i]);
            playIdx.put(plays[i], i);
            playlist.add(new Music(genres[i], plays[i]));
        }

        // 새로 알게 된 개념 -> Key 기준으로 정렬
        Map<String, Integer> genSort = new TreeMap<>(Collections.reverseOrder());
        genSort.putAll(genMap);

        // 리스트에 장르별 베스트 2개 담기
        List<Integer> list = new ArrayList<>();

        for(Map.Entry<String, Integer> gen : genSort.entrySet()) {
            List<Music> tmp = new ArrayList<>();

            for(Music m : playlist) {
                if(gen.getKey().equals(m.genre)) tmp.add(m);
            }

            Collections.sort(tmp);

            if(tmp.size() == 1) {
                list.add(playIdx.get(tmp.get(0).play));
            }
            else {
                list.add(playIdx.get(tmp.get(0).play));
                list.add(playIdx.get(tmp.get(1).play));
            }
        }

        int[] answer = new int[list.size()];
        for(int i=0; i<list.size(); i++) answer[i] = list.get(i);

        return answer;
    }
}

위 풀이의 결과

  • TreeMap의 역순 정렬은 Key(장르 이름) 알파벳 기준으로 정렬하는 것이라, 총 스트리밍 횟수 기준 정렬과 전혀 관계없다. 장르 순서가 완전히 잘못됐다.
  • playIdx에 plays[i] → i를 저장하는 방식은 같은 스트리밍 횟수를 가진 곡이 있으면 덮어씌워진다. 인덱스를 제대로 추적할 수 없는 구조다.
  • 히스토리 기준으로 20점 구간에 해당하는 풀이다.

2트 (오답)

→ playIdx의 덮어쓰기 문제를 인식하고, Music 객체에 인덱스(idx)를 직접 포함시켜 playIdx Map을 완전히 제거했다.
→ 덕분에 같은 스트리밍 횟수의 곡이 있어도 인덱스를 잃지 않게 됐다.
→ 그러나 장르 정렬 방식은 그대로 TreeMap(Collections.reverseOrder())를 유지했다. 이 부분이 여전히 문제임을 아직 파악하지 못한 상태였다.

import java.util.*;
// 음악 클래스
class Music implements Comparable<Music> {
    String genre;
    int play;
    int idx; // idx 필드 추가

    public Music(String genre, int play, int idx) {
        this.genre = genre;
        this.play = play;
        this.idx = idx;
    }

    @Override
    public int compareTo(Music m) {
        return m.play - this.play;
    }
}
class Solution {
    public int[] solution(String[] genres, int[] plays) {
        Map<String, Integer> genMap = new HashMap<>(); // 장르별 스트리밍 횟수 저장
        List<Music> playlist = new ArrayList<>(); // 곡별 스트리밍 횟수 저장

        for(int i=0; i<plays.length; i++) {
            genMap.put(genres[i], genMap.getOrDefault(genres[i],0) + plays[i]);
            playlist.add(new Music(genres[i], plays[i], i)); // playIdx 제거, idx를 객체에 직접 포함
        }

        // Key 기준 역순 정렬 (문제 있음 - 아직 미수정)
        Map<String, Integer> genSort = new TreeMap<>(Collections.reverseOrder());
        genSort.putAll(genMap);

        // 리스트에 장르별 베스트 2개 담기
        List<Integer> list = new ArrayList<>();

        for(Map.Entry<String, Integer> gen : genSort.entrySet()) {
            List<Music> tmp = new ArrayList<>();

            for(Music m : playlist) {
                if(gen.getKey().equals(m.genre)) tmp.add(m);
            }

            Collections.sort(tmp);

            if(tmp.size() == 1) {
                list.add(tmp.get(0).idx); // playIdx 대신 객체의 idx 직접 참조
            }
            else {
                list.add(tmp.get(0).idx);
                list.add(tmp.get(1).idx);
            }
        }

        int[] answer = new int[list.size()];
        for(int i=0; i<list.size(); i++) answer[i] = list.get(i);

        return answer;
    }
}

위 풀이의 결과

  • playIdx 덮어쓰기 문제는 해결됐다. Music 객체에 idx를 포함시킨 덕분에 인덱스 추적은 이제 정확하다.
  • 하지만 TreeMap(Collections.reverseOrder())는 Key인 장르 이름의 알파벳 역순으로 정렬한다. genMap의 Value(총 스트리밍 횟수)와는 아무 관계가 없어서 장르 순서가 여전히 틀렸다.
  • 히스토리 기준 13.3점 구간.

3트 (정답)

→ TreeMap Key 정렬 문제를 마침내 파악했다. 장르 정렬을 Value(총 스트리밍 횟수) 기준으로 바꿨다.
→ keySet을 꺼내 Comparator로 커스텀 정렬하는 방식으로 수정했다.

import java.util.*;
// 음악 클래스
class Music implements Comparable<Music> {
    String genre;
    int play;
    int idx;

    public Music(String genre, int play, int idx) {
        this.genre = genre;
        this.play = play;
        this.idx = idx;
    }

    @Override
    public int compareTo(Music m) {
        return m.play - this.play;
    }
}
class Solution {
    public int[] solution(String[] genres, int[] plays) {
        Map<String, Integer> genMap = new HashMap<>(); // 장르별 스트리밍 횟수 저장
        List<Music> playlist = new ArrayList<>(); // 곡별 스트리밍 횟수 저장

        for(int i=0; i<plays.length; i++) {
            genMap.put(genres[i], genMap.getOrDefault(genres[i],0) + plays[i]);
            playlist.add(new Music(genres[i], plays[i], i));
        }

        // Value 기준으로 정렬
        List<String> keySet = new ArrayList<>(genMap.keySet());
        keySet.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return genMap.get(o2) - genMap.get(o1);
            }
        });

        // 리스트에 장르별 베스트 2개 담기
        List<Integer> list = new ArrayList<>();

        for(String gen : keySet) {
            List<Music> tmp = new ArrayList<>();

            for(Music m : playlist) {
                if(gen.equals(m.genre)) tmp.add(m);
            }

            Collections.sort(tmp);

            if(tmp.size() == 1) {
                list.add(tmp.get(0).idx);
            }
            else {
                list.add(tmp.get(0).idx);
                list.add(tmp.get(1).idx);
            }
        }

        int[] answer = new int[list.size()];
        for(int i=0; i<list.size(); i++) answer[i] = list.get(i);

        return answer;
    }
}

위 풀이의 결과

  • genMap.keySet()을 꺼내 Comparator로 Value 기준 내림차순 정렬 → 장르 순서가 정확히 잡혔다.
  • Music 객체에 idx를 포함시켜 같은 재생 횟수여도 인덱스를 잃지 않는다.
  • 정확성 테스트 통과

3번의 시도를 돌아보면, 1트에서 2트로 넘어갈 때는 playIdx 덮어쓰기 문제를 잡았고, 2트에서 3트로 넘어갈 때는 TreeMap(reverseOrder())이 Key 알파벳 정렬임을 뒤늦게 깨달았다. 두 문제를 한 번에 잡지 못하고 한 번씩 나눠서 틀린 셈이다.
핵심은 "정렬 기준이 Value일 때는 keySet을 꺼내 Comparator로 직접 정렬" 하는 것, 그리고 "객체에 인덱스를 처음부터 포함시키는 것" 이다. 다음엔 더 빠르게 보이길 바라며.

'CS > 코딩테스트' 카테고리의 다른 글

프로그래머스 - 프로세스 (JAVA)  (0) 2026.04.24
프로그래머스 - 올바른 괄호 (JAVA)  (0) 2026.04.24
프로그래머스 - 기능개발 (JAVA)  (0) 2026.04.24
프로그래머스 - 같은 숫자는 싫어 (JAVA)  (0) 2026.04.23
프로그래머스 - 전화번호 목록 (JAVA)  (0) 2026.04.23
'CS/코딩테스트' 카테고리의 다른 글
  • 프로그래머스 - 올바른 괄호 (JAVA)
  • 프로그래머스 - 기능개발 (JAVA)
  • 프로그래머스 - 같은 숫자는 싫어 (JAVA)
  • 프로그래머스 - 전화번호 목록 (JAVA)
jupeternotebook
jupeternotebook
JUPETER의 취준, 개발, 일상
  • jupeternotebook
    JUPETER의 Notebook
    jupeternotebook
  • 전체
    오늘
    어제
    • 분류 전체보기 (18)
      • CS (18)
        • 자료구조 (2)
        • 알고리즘 (0)
        • 네트워크 (0)
        • 운영체제 (0)
        • 데이터베이스 (0)
        • 코딩테스트 (12)
        • GitHub (1)
        • Java (3)
      • 개발일지 (0)
      • 이모저모 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    jre
    우선순위큐
    jvm
    github
    덱
    메모리
    스택
    자료구조
    해시맵
    코딩테스트
    jdk
    java
    GC
    git
    해시
    프로그래밍언어
    heap
    프로그래머스
    큐
    해시셋
    힙
    stack
    정렬
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
jupeternotebook
프로그래머스 - 베스트 앨범 (JAVA)
상단으로

티스토리툴바