https://programmers.co.kr/learn/courses/30/lessons/42579
문제 설명
스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.
- 속한 노래가 많이 재생된 장르를 먼저 수록합니다.
- 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
- 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요.
제한사항
- genres[i]는 고유번호가 i인 노래의 장르입니다.
- plays[i]는 고유번호가 i인 노래가 재생된 횟수입니다.
- genres와 plays의 길이는 같으며, 이는 1 이상 10,000 이하입니다.
- 장르 종류는 100개 미만입니다.
- 장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.
- 모든 장르는 재생된 횟수가 다릅니다.
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
Map<String, List<Node>> map = new HashMap<>();
for (int i = 0; i < genres.length; i++){
String genre = genres[i];
int play = plays[i];
if (map.containsKey(genre)){
map.get(genre).add(new Node(i, play));
}
else {
List<Node> lst = new ArrayList<>();
lst.add(new Node(i, play));
map.put(genre, lst);
}
}
List<Genre> arr = new ArrayList<>();
for (String genre : map.keySet()){
int total = 0;
for (Node n : map.get(genre)){
total += n.play;
}
arr.add(new Genre(genre, total));
}
List<Integer> answer = new ArrayList<>();
Collections.sort(arr, new Comparator<Genre>(){
@Override
public int compare(Genre o1, Genre o2){
return o2.total - o1.total;
}
});
for (Genre g : arr){
String genre = g.genre;
List<Node> tmp = map.get(genre);
Collections.sort(tmp, new Comparator<Node>(){
@Override
public int compare(Node o1, Node o2){
if (o1.play == o2.play) return o1.index - o2.index;
else return o2.play - o1.play;
}
});
if (tmp.size() == 1) answer.add(tmp.get(0).index);
else {
answer.add(tmp.get(0).index);
answer.add(tmp.get(1).index);
}
}
int[] ans = new int[answer.size()];
for (int i = 0; i < answer.size(); i++){
ans[i] = answer.get(i);
}
return ans;
}
public class Node {
int index, play;
public Node(int index, int play){
this.index = index;
this.play = play;
}
}
public class Genre {
String genre;
int total;
public Genre(String genre, int total){
this.genre = genre;
this.total = total;
}
}
}
1. 어려웠던 점:
- Map에 장르를 키, 인덱스와 재생횟수를 담은 객체를 값으로 사용하는 것까지는 쉬웠으나
전체 재생 횟수를 어떻게 처리할지 고민을 많이 했다.
외부 IDE를 안쓰고 프로그래머스에서 작성하니 보다 어려웠다.
2. 알게된 점:
- Map을 사용하는 구현 복습
3. 알고리즘 풀이:
- Map에 장르를 key로 인덱스와 재생 횟수의 객체 리스트를 value로 정리해준다.
전부 정리되면, 새로운 리스트를 만들어 각 장르마다 전체 재생 횟수를 구해 내림차순으로 정렬해준다.
첫 번째 조건, 재생횟수가 많은 장르부터 선정이 가능해졌다.
- 위에서 만든 리스트는 전체 재생 횟수의 내림차순이므로,
앞에서부터 차례로 최대 두 곡을 꼽는다.
Map에서 장르에 맞는 인덱스, 재생 횟수 객체 리스트를 가져와
1. 재생 횟수 내림차순
2. 재생 횟수가 같으면, 인덱스 오름차순
으로 정렬해준다.
두 개 이상을 담고 있으면 두 개를 꼽고,
두 개가 안되면 (무조건 하나, 위에서 전체 재생 횟수를 계산해 존재하는 장르이기 때문에 없을 수 없다.) 하나를 꼽는다.
- 위에서 꼽은 리스트를 배열로 반환해준다.
'알고리즘 문제풀이 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] 다리를 지나는 트럭 with JAVA (0) | 2021.07.03 |
---|---|
[프로그래머스] 소수 찾기 with JAVA (0) | 2021.07.02 |
[프로그래머스] 더 맵게 with JAVA (0) | 2021.07.01 |
[프로그래머스] 위장 with JAVA (0) | 2021.06.24 |
[프로그래머스] 실패율 with JAVA (0) | 2021.04.28 |