99클럽 코테 스터디 5일차 TIL / [프로그래머스] 베스트앨범

전종원·2024년 7월 26일
0

오늘의 학습 키워드


HashMap, PriorityQueue, compareTo

문제


https://school.programmers.co.kr/learn/courses/30/lessons/42579

  • 플랫폼: 프로그래머스
  • 문제명: 베스트앨범
  • 난이도: Lv3

풀이


import java.util.*;

class Solution {
    public int[] solution(String[] genres, int[] plays) {
        Map<String, Integer> genreMap = new HashMap<>();
        Map<String, List<Music>> musicMap = new HashMap<>();
        List<Integer> ansList = new ArrayList<>();
        
        for(int i=0; i<genres.length; i++) {
            genreMap.put(genres[i], genreMap.getOrDefault(genres[i], 0) + plays[i]);
            
            if(!musicMap.containsKey(genres[i])) {
                musicMap.put(genres[i], new ArrayList<>());
            }
            
            musicMap.get(genres[i]).add(new Music(plays[i], i));
        }
        
        PriorityQueue<GenreInfo> genrePQ = new PriorityQueue<>();
        
        for(String genre : genreMap.keySet()) {
            genrePQ.offer(new GenreInfo(genre, genreMap.get(genre)));
        }
        
        while(!genrePQ.isEmpty()) {
            // 1번 기준
            GenreInfo genreInfo = genrePQ.poll();
            
            PriorityQueue<Music> musicPQ = new PriorityQueue<>();
            
            for(Music music : musicMap.get(genreInfo.genre)) {
                musicPQ.offer(music);
            }
                
            for(int i=0; i<2; i++) {
                // 장르에 속한 곡이 하나인 경우 예외처리
                if(musicPQ.isEmpty()) {
                    break;
                }
                
                Music music = musicPQ.poll();
                ansList.add(music.num);
            }
        }
        
        return ansList.stream().mapToInt(Integer::intValue).toArray();
    }
    
    public static class GenreInfo implements Comparable<GenreInfo> {
        String genre;
        int totalPlayCnt;
        
        public GenreInfo(String genre, int totalPlayCnt) {
            this.genre = genre;
            this.totalPlayCnt = totalPlayCnt;
        }
        
        @Override
        public int compareTo(GenreInfo g) { // 1번 기준
            return g.totalPlayCnt - this.totalPlayCnt;
        }
    }
    
    public static class Music implements Comparable<Music> {
        int playCnt;
        int num;
        
        public Music(int playCnt, int num) {
            this.playCnt = playCnt;
            this.num = num;
        }
        
        @Override
        public int compareTo(Music m) {
            if(this.playCnt == m.playCnt) { // 3번 기준
                return this.num - m.num;
            }
            
            return m.playCnt - this.playCnt; // 2번 기준
        }
    }
}

접근

  • 문제에 정의된 노래 수록 기준 3가지를 모두 compareTo 메서드 오버라이딩을 통해 정의했고, 우선순위 큐를 활용하여 올바른 순서로 추출될 수 있도록 구현했습니다.
    • 첫 번째 수록 기준인 “속한 노래가 많은 재생된 장르를 먼저 수록합니다.” 는 GenreInfo 클래스를 정의하여 장르의 전체 재생 횟수를 집계한 뒤 가장 많이 재생된 장르가 먼저 추출될 수 있도록 했습니다.
    • 나머지 수록 기준은 Music 클래스에 정렬 기준을 구현했습니다.
  • 다른 분들은 대부분 별도의 클래스 생성 없이 람다식을 활용해 짧게 구현하셨더라고요! GenreInfo 클래스 대신 람다식을 활용한 코드로 리팩토링 해봤습니다.
    import java.util.*;
    
    class Solution {
        public int[] solution(String[] genres, int[] plays) {
            Map<String, Integer> genreMap = new HashMap<>();
            Map<String, List<Music>> musicMap = new HashMap<>();
            List<Integer> ansList = new ArrayList<>();
    
            for(int i=0; i<genres.length; i++) {
                genreMap.put(genres[i], genreMap.getOrDefault(genres[i], 0) + plays[i]);
    
                if(!musicMap.containsKey(genres[i])) {
                    musicMap.put(genres[i], new ArrayList<>());
                }
    
                musicMap.get(genres[i]).add(new Music(plays[i], i));
            }
    
            List<String> genreList = new ArrayList<>(genreMap.keySet());
            Collections.sort(genreList, ((o1, o2) -> genreMap.get(o2) - genreMap.get(o1)));
    
            for (String genre : genreList) {
                PriorityQueue<Music> musicPQ = new PriorityQueue<>();
    
                for(Music music : musicMap.get(genre)) {
                    musicPQ.offer(music);
                }
    
                for(int i=0; i<2; i++) {
                    // 장르에 속한 곡이 하나인 경우 예외처리
                    if(musicPQ.isEmpty()) {
                        break;
                    }
    
                    Music music = musicPQ.poll();
                    ansList.add(music.num);
                }
            }
    
            return ansList.stream().mapToInt(Integer::intValue).toArray();
        }
    
        public static class Music implements Comparable<Music> {
            int playCnt;
            int num;
    
            public Music(int playCnt, int num) {
                this.playCnt = playCnt;
                this.num = num;
            }
    
            @Override
            public int compareTo(Music m) {
                if(this.playCnt == m.playCnt) { // 3번 기준
                    return this.num - m.num;
                }
    
                return m.playCnt - this.playCnt; // 2번 기준
            }
        }
    }

소요 시간

30분

회고


stream과 람다식 적극 활용하기

0개의 댓글