스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.
속한 노래가 많이 재생된 장르를 먼저 수록합니다.
장르 내에서 많이 재생된 노래를 먼저 수록합니다.
장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
Map<String, Integer> genrePlayCount = new HashMap<>(); // 각 장르에 대한 재생횟수
Map<String, List<int[]>> genreSongList = new HashMap<>();
// 장르별 재생횟수와 인덱스 값 저장
// HashMap에 장르별 재생 횟수 총합 계산
for (int i = 0; i < genres.length; i++) {
genrePlayCount.put(genres[i], genrePlayCount.getOrDefault(genres[i], 0) + plays[i]);
// 각 장르에 해당하는 노래 정보 없으면 새로 만듦 [인덱스값, 재생횟수]
if (!genreSongList.containsKey(genres[i])) {
genreSongList.put(genres[i], new ArrayList<>());
}
// 장르와 인덱스 값(i), 재생횟수 저장
genreSongList.get(genres[i]).add(new int[]{i, plays[i]});
}
// {"pop", "classic"} 형태로 장르 반환
List<String> genreList = new ArrayList<>(genrePlayCount.keySet());
// 장르별 총 재생 횟수를 기준으로 내림차순 정렬
genreList.sort((g1, g2) -> genrePlayCount.get(g2) - genrePlayCount.get(g1));
// 결과 저장 리스트 생성
List<Integer> result = new ArrayList<>();
// 각 장르별로 가장 많이 재생된 상위 2곡 추출
for (String genre : genreList) { // genreList는 {"pop", "classic"}
List<int[]> songs = genreSongList.get(genre);
songs.sort((s1, s2) -> s2[1] - s1[1]); // 재생횟수를 기준으로 내림차순 정렬
// 가장 많이 재생된 2곡만 선택
int count = 0;
for (int[] song : songs) {
if (count >= 2) break;
result.add(song[0]); // 인덱스만 저장
count++;
}
}
// 결과를 리스트에서 int[] 배열로 반환
return result.stream().mapToInt(i -> i).toArray();
}
}
장르와 노래 재생 횟수, 고유번호인 인덱스값 3가지가 필요하므로, 먼저
HashMap에 각 장르의 재생횟수 총합을 구하고, 또 다른 하나의 키 장르에 고유번호와 재생횟수 2개의 값을 갖는 HashMap을 만든다.
✨HashMap 자체는 정렬되지않으므로, Map을 리스트로 변환하는 작업이 필요하다.
정렬을 위해 리스트를 생성하여 키 값인 장르를 넣고, 그 키를 기준으로 장르별 재생횟수를 내림차순으로 정렬 후 저장한다. >> 노래가 많이 재생된 장르 구함
장르 내에서 많이 재생된 노래를 먼저 수록하기 위해,
새로 생성된 노래 리스트에
하나의 키 장르에 고유번호와 재생횟수 2개의 값이 저장된 genreSongList 맵을 이용하여
넣고 그 값들을 내림차순 후, 결과 리스트에 상위 2곡의 인덱스(고유번호)만 저장한다.
"pop" = [{0,200}.[3.150}..] >> 1개의 장르 키와 2개의 값 형태
리스트를 Int배열로 반환하기 위해,
결과 리스트를 스트림으로 바꾸고, 스트림의 각 요소를 int로 변환 후(Integer -> int), 배열로 변환한다.
return result.stream().mapToInt(i -> i).toArray();