[Java] 프로그래머스 Hash - 베스트앨범 (Lv3)

JuhyunKim·2022년 11월 3일
0

코딩테스트

목록 보기
5/8

프로그래머스 - 베스트앨범
https://school.programmers.co.kr/learn/courses/30/lessons/42579


베스트앨범

HashMap을 이용한 풀이

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

/*
    genreMap : key-장르, value-장르의 속하는 곡 고유번호와 재생횟수
    genreCountMap : key-장르, value-장르가 재생된 횟수 총합
    genreSortedList : 장르가 재생된 횟수가 많은 순으로 정렬된 장르명 리스트
*/

class Solution {
    public int[] solution(String[] genres, int[] plays) {
        List<Integer> answer = new ArrayList<>();
       
        Map<String, List<Integer[]>> genreMap = new HashMap<>();
        Map<String, Integer> genreCountMap = new HashMap<>();
        List<String> genreSortedList = new ArrayList<>();

        for(int i=0; i<genres.length; ++i){
            final int idx = i;
            List<Integer[]> list = genreMap.getOrDefault(genres[idx], new ArrayList<>());
            list.add(new Integer[] {idx, plays[idx]});
            genreMap.put(genres[idx], list);
            genreCountMap.put(genres[idx], genreCountMap.getOrDefault(genres[idx],0)+plays[idx]);
        }
       
        for(String key : genreCountMap.keySet()) 
            genreSortedList.add(key);
        Collections.sort(genreSortedList, (o1, o2) -> genreCountMap.get(o2) - genreCountMap.get(o1)); 

        for(String genre : genreSortedList){
            List<Integer[]> playList = genreMap.get(genre);
            Collections.sort(playList, (s1, s2) -> s2[1] - s1[1]);
            answer.add(playList.get(0)[0]);
            if(playList.size()>1) answer.add(playList.get(1)[0]);
        }
               
        return answer.stream().mapToInt(Integer::intValue).toArray();
    }
}

일단 HashMap만 사용해서 풀이는 해봤는데..
중간에 sorting을 여러번 진행할 때부터 미리 객체로 빼놨어야 했음을 알았다..
근데 일단 객체로 분리하지 않고 하는 방법으로 진행해봤다.
프로세스 자체에는 문제가 없어서 정답은 맞지만, 코드가독성이 너무 떨어진다.
변수가 많아질 때부터 단단히 잘못됐음을..

Album을 객체(Object)로

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

class Solution {
  
    class Album implements Comparable<Album> {
        String genre;
        int number;
        int playCount;
       
        Album(String genre, int number, int playCount){
            this.genre = genre;
            this.number = number;
            this.playCount = playCount;
        }
       
        @Override
        public int compareTo(Album o) {
          if(this.playCount == o.playCount) return this.number - o.number;
          return o.playCount - this.playCount;
        }
    }
   
    private int sumPlayCount(List<Album> albums){
        int answer = 0;
        for(Album album : albums){
            answer += album.playCount;
        }
        return answer;
    }
   
    public int[] solution(String[] genres, int[] plays) {
        List<Integer> answer = new ArrayList<>();
        Map<String, List<Album>> map = new HashMap<>();
       
        for(int idx=0; idx<genres.length; ++idx){
            List<Album> albums = map.getOrDefault(genres[idx], new ArrayList<>());
            albums.add(new Album(genres[idx], idx, plays[idx]));
            map.put(genres[idx], albums);
        }

        List<String> genreSortedList = new ArrayList<>();
        for(String key : map.keySet()) genreSortedList.add(key);
        Collections.sort(genreSortedList, (o1, o2) -> sumPlayCount(map.get(o2)) - sumPlayCount(map.get(o1)));

        for(String genre : genreSortedList){
            List<Album> albums = map.get(genre);
            Collections.sort(albums, (o1, o2) -> o1.compareTo(o2));
            answer.add(albums.get(0).number);
            if(albums.size()>1) answer.add(albums.get(1).number);
        }
       
        return answer.stream().mapToInt(Integer::intValue).toArray();
    }
}

객체로 묶어서 코드가독성은 좋아졌는데, 사실 효율성은 거의 그대로인 것 같다.
Stream 사용하면 훨씬 간단하게도 되는 것 같던데 일단 stream은 표현식이 간단해서 좋지만 효율성이 별로기도 하고 Hash를 익히는게 목적이라 일단 여기까지 하기로.



사담? 후기?) 프로그래머스 고득점 Kit - Hash 5문제를 풀어봤는데 중복이 허용되지 않는 HashSet과 key와 value를 한 쌍으로 저장할 수 있는 HashMap이 중요포인트. 어떻게 사용하는지는 어느 정도 익힌 것 같다. 사실 문법이 달라서 그렇지 dart에서 사용하던 Set과 Map과 특징은 거의 비슷해서 크게 어려움은 없었던 것 같다.

0개의 댓글