✔ 베스트앨범
문제 분석하기
장르별로 가장 먼저 정렬을 한 후, 장르 중에서 상위 2개를 뽑아 그에 대한 앨범을 만들어서 반환해야 함
손으로 풀어보기
- HashMap을 사용해 장르에 따른 총 재생 횟수를 저장
- 재생횟수가 많은 순서대로 장르 선정
- 선정된 장르를 가진 노래 중 가장 많이 재생된 노래 하나 이상 선택
- 이때 재생 횟수가 같다면 고유 번호가 낮은 노래를 먼저 수록
- 장르에 따라 선정된 노래들의 고유 번호를 모아 반환
슈도코드 작성하기
genres(노래의 장르를 나타내는 문자열 배열)
plays(노래별 재생 횟수를 나타내는 정수 배열)
answer(결과 list)
장르 순서 선정 함수
장르별 노래 선정 함수
answer를 배열로 변환하여 반환
장르 순서 선정 함수 {
map(노래 장르별 재생횟수를 저장하는 hashMap)
for(genres만큼) {
map에 노래 장르와 재생횟수를 저장
}
genres_oder(재생횟수가 많은 순서대로 장르를 저장하는 list)
리스트 정렬을 커스텀하여 내림차순으로 genres_order에 map 저장
}
장르별 노래 선정 함수 {
for(genres_order만큼) {
musics(장르별 고유 번호와 재생 횟수를 담은 music을 저장하는 list)
for(genres만큼) {
if(둘의 장르가 동일하다면) {
musics에 music 저장
}
}
리스트 정렬을 커스텀하여 내림차순으로 musics 정렬
answer에 musics 리스트의 노래 중 첫 번째 고유번호 저장
if(musics의 크기가 1보다 크다면) {
answer에 musics 리스트의 노래 중 두 번째 고유번호 저장
}
}
}
music {
idx(고유 번호), play(재생 횟수)
}
코드 구현하기
/**
* 42579) 베스트앨범
*/
public class K005_42579 {
static ArrayList<String> genres_order;
static ArrayList<Integer> answer;
// genres(노래의 장르를 나타내는 문자열 배열)
// plays(노래별 재생 횟수를 나타내는 정수 배열)
public int[] solution(String[] genres, int[] plays) {
// answer(결과 list)
answer = new ArrayList<>();
// 장르 순서 선정 함수
selectGenreOrder(genres, plays);
// 장르별 노래 선정 함수
selectSongByGenre(genres, plays);
// answer를 배열로 변환하여 반환
return answer.stream().mapToInt(i -> i).toArray();
}
// 장르 순서 선정 함수
private void selectGenreOrder(String[] genres, int[] plays) {
// map(노래 장르별 재생횟수를 저장하는 hashMap)
Map<String, Integer> map = new HashMap<>();
// map에 노래 장르와 재생횟수를 저장
for (int i = 0; i < genres.length; i++) {
map.put(genres[i], map.getOrDefault(genres[i], 0) + plays[i]);
}
// genres_oder(재생횟수가 많은 순서대로 장르를 저장하는 list)
genres_order = new ArrayList<>(map.keySet());
// 리스트 정렬을 커스텀하여 내림차순으로 genres_order에 map 저장
genres_order.sort((o1, o2) -> map.get(o2) - map.get(o1));
}
// 장르별 노래 선정 함수
private void selectSongByGenre(String[] genres, int[] plays) {
for (String genre : genres_order) {
// musics(장르별 고유 번호와 재생 횟수를 담은 music을 저장하는 list)
ArrayList<music> musics = new ArrayList<>();
for (int i = 0; i < genres.length; i++) {
// 장르가 동일하다면
if (genre.equals(genres[i])) {
// musics에 music 저장
musics.add(new music(i, plays[i]));
}
}
// 리스트 정렬을 커스텀하여 내림차순으로 musics 정렬
musics.sort(new Comparator<music>() {
@Override
public int compare(music o1, music o2) {
// 재생횟수가 같다면
if (o1.play == o2.play) {
// 고유번호가 작은 순서대로 오름차순
return o1.idx - o2.idx;
}
// 재생횟수가 많은 순서대로 내림차순
return o2.play - o1.play;
}
});
// answer에 musics 리스트의 노래 중 첫 번째 고유번호 저장
answer.add(musics.get(0).idx);
// musics의 크기가 1보다 크다면
if (musics.size() > 1) {
// answer에 musics 리스트의 노래 중 두 번째 고유번호 저장
answer.add(musics.get(1).idx);
}
}
}
// 테스트 케이스
public static void main(String[] args) {
K005_42579 solution = new K005_42579();
String[] genres = { "classic", "pop", "classic", "classic", "pop" };
int[] plays = { 500, 600, 150, 800, 2500 };
int[] result = solution.solution(genres, plays);
System.out.println(Arrays.toString(result));
}
}
// music
class music {
// idx(고유 번호)
int idx;
// play(재생 횟수)
int play;
music(int idx, int play) {
this.idx = idx;
this.play = play;
}
}
'Coding Test > Java 알고리즘 실전' 카테고리의 다른 글
[42583] 다리를 지나는 트럭 (0) | 2023.11.28 |
---|---|
[42587] 프로세스 (0) | 2023.11.27 |
[42578] 의상 (0) | 2023.11.26 |
[1844] 게임 맵 최단거리 (0) | 2023.11.26 |
[42898] 등굣길 (0) | 2023.11.25 |