Search
Duplicate
📒

[Programmers] 01-3. 베스트앨범 ⭐

상태
완료
수업
Algorithm Solving
주제
Programmers
4 more properties
참고

문제해설

NOTE
입력 값 ⇒ 문자열 배열(음악장르), 정수 배열(재생 수)
출력 값 ⇒ 장르, 재생 수, 고유번호 순으로 나열된 음악 정수배열

문제 로직고민

NOTE
Map을 사용하면서 key(장르)의 value(총 재생수) 순으로 어떻게 정렬하는가?
Map은 key값으로는 정렬이 가능하지만 value로는 정렬이 불가능하다.
정렬이 가능한 자료구조로 변경한다음 정렬한 값을 사용한다!
동일 장르의 재생 수 정렬은 어떻게 정렬하는가?
key(장르), value([음악 id, 재생수]) 형식으로 작성한 다음, value값을 정렬해주면 된다.

작성코드

NOTE
class Solution { public int[] solution(String[] genres, int[] plays) { Map<String, Integer> genresMap = new HashMap<>(); Map<String, List<int[]>> playsMap = new HashMap<>(); // 장르별 총 재생수를 구한다. for (int i = 0; i < genres.length; i++) { String genre = genres[i]; int play = plays[i]; genresMap.put(genre, genresMap.getOrDefault(genre, 0) + play); playsMap.putIfAbsent(genre, new ArrayList<>()); playsMap.get(genre).add(new int[]{i, play}); } // 각 장르의 음악을 재생수로 내림차순 정렬한다. for (Map.Entry<String, List<int[]>> entry : playsMap.entrySet()) { entry.getValue().sort((s1, s2) -> { if (s1[1] != s2[1]) { return Integer.compare(s2[1], s1[1]); } else { return Integer.compare(s1[0], s2[0]); } }); } // 각 장르의 총 재생수를 내림차순으로 정렬한다. List<Map.Entry<String, Integer>> genresList = new ArrayList<>(genresMap.entrySet()); genresList.sort(Map.Entry.<String, Integer>comparingByValue().reversed()); // 각 장르의 재생수 1,2위를 수록한다. List<Integer> result = new ArrayList<>(); for (int i=0; i<genresList.size(); i++) { Map.Entry<String, Integer> entry = genresList.get(i); String genre = entry.getKey(); List<int[]> playList = playsMap.get(genre); for (int j = 0; j < Math.min(2, playList.size()); j++) { result.add(playList.get(j)[0]); } } return result.stream().mapToInt(i -> i).toArray(); } }
Java
복사
로직은 생각했는데 구현이 어려웠다.
Map → List로 변환한뒤 정렬하는 람다함수를 구현하는 방법을 몰라서 검색을 진행했다.
문제를 제대로 읽지 않아 장르에서 상위 2개가 아닌, 상위 장르 2개의 음악을 초기에 가져왔다.
List → 배열변환은 꼭 기억해두자.

다른사람 풀이

NOTE
public class Solution { public class Music implements Comparable<Music>{ private int played; private int id; private String genre; public Music(String genre, int played, int id) { this.genre = genre; this.played = played; this.id = id; } @Override public int compareTo(Music other) { if(this.played == other.played) return this.id - other.id; return other.played - this.played; } public String getGenre() {return genre;} } public int[] solution(String[] genres, int[] plays) { return IntStream.range(0, genres.length) .mapToObj(i -> new Music(genres[i], plays[i], i)) .collect(Collectors.groupingBy(Music::getGenre)) .entrySet().stream() .sorted((a, b) -> sum(b.getValue()) - sum(a.getValue())) .flatMap(x->x.getValue().stream().sorted().limit(2)) .mapToInt(x->x.id).toArray(); } private int sum(List<Music> value) { int answer = 0; for (Music music : value) { answer+=music.played; } return answer; } }
Java
복사
스트림 사용코드
스트림을 정말로 잘쓰는 코드다. groupingBy를 적극적으로 활용해 Map으로 사용하는 방식을 잘 알아두면 좋을것 같다.
이외에도 우선순위 큐 방식도 있긴하던데, 2개의 Map을 사용한 방법이 정석같아 따로 가져오진 않았다.