Problem Solving/Online Judge
[프로그래머스] 베스트 앨범
se0m
2024. 8. 21. 16:42
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
💬 문제 설명
노래들의 장르와 재생 횟수가 주어졌을 때, 주어진 조건대로 정렬하고 각 장르 별로 최대 2개의 노래만 리턴하도록 한다.
1. 속한 노래가 많이 재생된 장르를 먼저 수록합니다. (장르 별 총 재생횟수로 내림차 순)
2. 장르 내에서 많이 재생된 노래를 먼저 수록합니다. (재생 횟수로 내림차 순)
3. 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다. (고유 번호로 오름차 순)
📌 주의 사항
- 장르 별로 가장 많이 재생된 노래를 최대 두 개까지 모아 베스트 앨범을 출시하므로 특정 장르에 노래가 하나인 경우에는 하나의 노래만 수록하도록 한다.
👌 문제 풀이
- 장르별 총 재생 횟수를 담는` Map`과 장르별 노래 리스트를 담는 `Map`을 선언한다.
- 노래 정보를 담을 Song 클래스를 정의하고 `Comparable` 인터페이스를 구현하여 `compareTo()`를 재정의한다.
- 장르별 총 재생 횟수와 장르별 노래 리스트를 구한다.
- 장르별 총 재생 횟수 `Map`에서 값(총 재생 횟수)으로 `Map`을 정렬한다.
- 위에서 정렬한 순서대로 장르를 받아 해당 장르의 노래 리스트를 정렬한다.
- 사이즈에 따라 1개 or 2개를 출력한다.
- 리스트를 배열로 변환한다.
💻 코드
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Solution {
public int[] solution(String[] genres, int[] plays) {
List<Integer> answer = new ArrayList<>();
// 장르: 총 재생 횟수
Map<String, Integer> genrePlayCnt = new HashMap<>();
// 장르: 노래 리스트
Map<String, List<Song>> genreSongs = new HashMap<>();
for (int i = 0; i < genres.length; i++) {
// 장르별 총 재생 횟수를 구한다.
if (genrePlayCnt.get(genres[i]) == null) {
// 초기화
genrePlayCnt.put(genres[i], 0);
}
int cnt = genrePlayCnt.get(genres[i]) + plays[i];
genrePlayCnt.put(genres[i], cnt);
// 장르별 노래 리스트를 구성한다.
if (genreSongs.get(genres[i]) == null) {
// 초기화
genreSongs.put(genres[i], new ArrayList<>());
}
List<Song> temp = genreSongs.get(genres[i]);
temp.add(new Song(i, plays[i]));
genreSongs.put(genres[i], temp);
}
// 키(장르)만 뽑아내서 리스트 구성
List<String> keySet = new ArrayList<>(genrePlayCnt.keySet());
// 키 리스트를 이용해서 값(총 재생 횟수)의 내림차순 정렬
keySet.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return genrePlayCnt.get(o2).compareTo(genrePlayCnt.get(o1));
}
});
for (String genre : keySet) {
// 장르별 노래 리스트 정렬
Collections.sort(genreSongs.get(genre));
for (int i = 0; i < 2; i++) {
// 사이즈에 따라 1개, 2개 출력 결정
if (genreSongs.get(genre).size() > i) {
answer.add(genreSongs.get(genre).get(i).id);
}
}
}
// 리스트 -> 배열
int[] answerArray = new int[answer.size()];
for (int i = 0; i < answer.size(); i++) {
answerArray[i] = answer.get(i);
}
return answerArray;
}
}
class Song implements Comparable<Song> {
int id;
int playCnt;
public Song(int id, int playCnt) {
this.id = id;
this.playCnt = playCnt;
}
@Override
public int compareTo(Song other) {
// 재생 횟수가 같으면 고유 번호의 오름차 순 정렬
if (other.playCnt == this.playCnt) {
return this.id - other.id;
}
// 재생횟수의 오름차 순으로 정렬
return other.playCnt - this.playCnt;
}
}
🎓 배운 것
- Map에서 Value 기준으로 정렬할 때는 `keySet()`으로 Map의 Key 값만 빼와서 리스트를 구성하고 이 리스트로 `Comparator` 인터페이스를 구현해서 정렬한다.
☞ 결과 값은 값을 기준으로 정렬된 키의 리스트 ❗ 이므로 정렬된 Map을 사용하려면 이 정렬된 키 리스트를 이용해서 Map의 값에 접근해야 한다.