Hash - 베스트 엘범
문제
매개변수로 각 고유번호 i 번째 노래 각각의 장르 정보가 주어지는 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어진다.
하나의 엘범에, 장르별로 가장 많이 재생된 노래를 최대 2곡씩 뽑아 엘범을 구성하려한다.
- 속한 노래가 많이 재생된 장르를 먼저 수록합니다.
- 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
- 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
Step 1. 문제 접근
전체 노래 재생 횟수가 가장 많은 장르 순서대로 가장 재생횟수가 많은 곡 두곡씩을 뽑는다.
Step 2. 선택한 알고리즘
해시맵과 정렬
Step 3. 선택 이유
-
곡의 장르를 하나씩 검증하면서
-
각 장르를 key로 하는 HashMap<장르, 곡 HashMap>를 생성 (만약 key로 조회되는 장르가 없으면)
-
Hash에서 해당 장르의 list을 가져와서 Entry형태로 삽입하고
-
재생 횟수 누적 합을 구해 내림차순으로 배열에 장르를 넣는다.
Step 4. 구현 (코드)
import java.util.* ;
class Solution {
public int[] solution(String[] genres, int[] plays) {
List<Integer> answer = new ArrayList<>();
Map<String, Map<Integer, Integer>> maps = new HashMap<>();
// <장르, <곡번호, 재생횟수>>로 해시맵 생성
for (String genre : genres) { // 각 장르마다
maps.put(genre, new HashMap<>()); // 곡정보(곡 리스트)를 저장할 HashMap 생성 후 넣어줌
}
for (int i = 0; i < genres.length; i++) { // 곡을 하나씩 검사하면서
maps.get(genres[i]).put(i, plays[i]); // 해당 장르의 곡 리스트를 가져와서 곡 정보, 즉 <고유번호, 재생횟수> 를 추가해줌 => 장르별 곡 리스트 완성
}
Map<String, Integer> maps2 = new HashMap<>(); // <장르, 총재생횟수>를 저장할 두번째 HashMap 생성
for (String s : maps.keySet()) { // 장르별 곡 리스트 map에서 key값들, 즉 장르들만 가져옴
int count = maps.get(s) // 각 장르별 곡리스트, <곡번호, 재생횟수>를 가져와서
.values() // 재생횟수만 뽑아옴
.stream().mapToInt(n -> n) // 곡들의 재생횟수들을 스트림으로 변환해서
.sum() ; // 합친값을 반환 => 총 재생횟수
maps2.put(s, count); // <장르, 총 재생횟수> 를 map에 삽입
}
List<String> keySetList = new ArrayList<>(maps2.keySet());
// key값들 즉 곡의 장르들 가져와서 List생성 (for 정렬)
keySetList.sort((o1, o2) -> (maps2.get(o2).compareTo(maps2.get(o1))));
// 그 장르들을 총 재생횟수 순으로 정렬 (o1, o2 는 장르 즉 key값, 정렬 기준은 그 키값을 기준으로 maps2에서 가져온 value값 즉 총재생횟수!)
keySetList.forEach(s -> { // 총재생횟수 순으로 정렬된 장르들을 순서대로 가져오면서, 즉 장르들을 하나씩 검사하면서
Map<Integer, Integer> songList = maps.get(s); // <장르, 곡리스트>가 저장된 HashMap에서 해당 장르의 곡리스트(<곡번호, 재생횟수>) 를 가져오고
List<Integer> integers = new ArrayList<>(songList.keySet());
// 곡번호들로 새로운 list 생성 (곡 리스트를 재생횟수(value 값) 순으로 정렬하기 위해 Map을 List로 변환 )
integers.sort((o1, o2) -> (songList.get(o2).compareTo(songList.get(o1))));
// 곡리스트의 곡번호들을 재생횟수 순으로 정렬 (o1, o2 는 곡번호 즉 key값, 정렬 기준은 그 키값을 기준으로 가져온 재생횟수값 - 내림차순)
if (integers.size() <= 1) { // 해당 장르의 곡 갯수가 1개 이하면
answer.add(integers.get(0)); // 하나만 추가 (곡 번호)
} else { // 두개 이상이면
answer.add(integers.get(0)); // 가장 많은 두개 추가 (곡 번호)
answer.add(integers.get(1));
}
}); // x 각 장르별로 반복
return answer.stream().mapToInt(i -> i).toArray();
// 곡번호들로 구성된 ArrayList를 Array로 변환해서 반환
}
}
댓글남기기