티스토리 뷰
문제 : programmers.co.kr/learn/courses/30/lessons/42579
코딩테스트 연습 - 베스트앨범
스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다. 속한 노래가
programmers.co.kr
아이디어
1. 장르 데이터 정리
Map<장르명, 총 재생수> 변수를 사용하여 각 장르별 총 재생수를 계산한다.
장르 명, 총 재생수를 멤버 변수로 가지는 Genre class를 정의하고, Comparable을 implements 하여 총 재생수를 바탕으로 Genre끼리 대소비교가 가능하도록 해 준다. 이 때, 내림차순으로 정렬될 수 있도록 한다.
위 Map에 만들어놓은 정보를 바탕으로 각 장르별로 Genre class의 instance를 만들고, PriorityQueue를 사용해 내림차순으로 정렬시킨다.
2. 각 장르별 노래 데이터 정리
Map<장르명, PriorityQueue<노래>> 변수를 사용하여 각 장르마다 그 장르에 속한 노래들에 대한 정보를 정리한다.
Song class는 멤버 변수로 고유 번호와 재생 횟수를 가지도록 하고, Comparable을 implements 하여 재생 수를 바탕으로 Song class의 instance끼리 대소비교가 가능하도록 해 준다. 마찬가지로 내림차순으로 정렬될 수 있도록 한다.
주어진 genres, plays array를 순회하며, Map.get(genres[i]) 를 통해 얻을 수 있는 해당 장르의 PriorityQueue에 재생 횟수 plays[i], 고유 번호 i를 가지는 Song class의 instance를 offer 한다.
3. 정답 확인
1의 PrioritQueue에서 poll을 하면 차례대로 총 재생횟수가 많은 베스트 장르를 얻을 수 있다.
2의 Map에서 위 결과를 get 하면, 해당 장르의 노래들을 담은 PriorityQueue를 얻을 수 있다. 이 PriorityQueue에서 최대 2개의 원소를 poll한다.
이 과정을 1의 PriorityQueue가 empty 될 때 까지 반복한다.
소스코드
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
Map<String, Integer> plays4EachGenre = new HashMap<>(); // 장르명 : 총재생수
for (int i = 0; i < genres.length; i++) {
plays4EachGenre.put(genres[i], plays4EachGenre.getOrDefault(genres[i], 0) + plays[i]);
}
// 1. 인기 "장르" 정렬
PriorityQueue<Genre> bestGenres = new PriorityQueue<>();
Set<String> genreNames = plays4EachGenre.keySet();
for (String bestGenre : genreNames) {
bestGenres.offer(new Genre(bestGenre, plays4EachGenre.get(bestGenre)));
}
// 1-2. 각 장르별 Song 정렬
Map<String, PriorityQueue<Song>> bestSongs4EachGenre = new HashMap<>();
for (int i = 0; i < genres.length; i++) {
PriorityQueue<Song> pq4Songs = bestSongs4EachGenre.getOrDefault(genres[i], new PriorityQueue<>());
pq4Songs.offer(new Song(plays[i], i));
bestSongs4EachGenre.put(genres[i], pq4Songs);
}
// 2. 각 장르별 최대 2곡까지 뽑기
List<Integer> answer = new ArrayList<>();
while (!bestGenres.isEmpty()) {
Genre currentGenre = bestGenres.poll();
String currentGenreName = currentGenre.getGenreName();
PriorityQueue<Song> pq4SongsOfEachGenre = bestSongs4EachGenre.get(currentGenreName);
int size = Math.min(pq4SongsOfEachGenre.size(), 2);
for (int i = 0; i < size; i++) {
answer.add(Objects.requireNonNull(pq4SongsOfEachGenre.poll()).getRegNo());
}
}
return answer.stream().mapToInt(i -> i).toArray();
}
}
class Song implements Comparable<Song> {
private final int plays;
private final int regNo;
Song(int plays, int regNo) {
this.plays = plays;
this.regNo = regNo;
}
public String getGenre() {
return this.genre;
}
public int getPlays() {
return this.plays;
}
public int getRegNo() {
return this.regNo;
}
@Override
public int compareTo(Song o) {
return o.getPlays() - this.plays;
}
}
class Genre implements Comparable<Genre> {
private final String genreName;
private final int totalPlays;
Genre(String genreName, int totalPlays) {
this.genreName = genreName;
this.totalPlays = totalPlays;
}
public String getGenreName() {
return this.genreName;
}
public int getTotalPlays() {
return this.totalPlays;
}
@Override
public int compareTo(Genre o) {
return o.getTotalPlays() - this.totalPlays;
}
}
Review
아직 첫 번째 풀이여서 내용도, 아이디어도 깔끔하게 정리가 되지 못했다. 불필요한 중복도 보이고 수정/개선할 부분이 남아있다.
좀 더 유형정리를 잘 해 두어서 다음번 풀이때에는 보다 깔끔하고 빠르게 구현할 수 있도록 해 두어야겠다.
'알고리즘 문제 > Programmers' 카테고리의 다른 글
[프로그래머스] 위장 - Java (0) | 2021.04.28 |
---|---|
[프로그래머스] 전화번호 목록 - Java (0) | 2021.04.28 |
[프로그래머스] 완주하지 못한 선수 - Java (0) | 2021.04.20 |
[프로그래머스] 여행경로 - Java (0) | 2021.04.19 |
[프로그래머스] 단어변환 - Java (0) | 2021.04.14 |
- Total
- Today
- Yesterday
- Sorting
- 자료구조
- 연습문제
- 멀리 뛰기
- 백준
- BFS
- stack
- 탐욕법
- dynamic programming
- 코딩테스트
- java
- DP
- 자바
- Algorithm
- programmers
- 해시
- Queue
- dfs
- Hash
- 큐
- 동적계획법
- Heap
- 데브코스
- 프로그래머스
- 힙
- 정렬
- greedy
- 완전탐색
- 그래프
- 알고리즘
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |