참고
문제해설
문제 로직고민
NOTE
•
Map을 사용하면서 key(장르)의 value(총 재생수) 순으로 어떻게 정렬하는가?
◦
Map은 key값으로는 정렬이 가능하지만 value로는 정렬이 불가능하다.
◦
정렬이 가능한 자료구조로 변경한다음 정렬한 값을 사용한다!
•
동일 장르의 재생 수 정렬은 어떻게 정렬하는가?
◦
key(장르), value([음악 id, 재생수]) 형식으로 작성한 다음, value값을 정렬해주면 된다.
작성코드
NOTE
class Solution {
public int[] solution(String[] genres, int[] plays) {
Map<String, Integer> genresMap = new HashMap<>();
Map<String, List<int[]>> playsMap = new HashMap<>();
// 장르별 총 재생수를 구한다.
for (int i = 0; i < genres.length; i++) {
String genre = genres[i];
int play = plays[i];
genresMap.put(genre, genresMap.getOrDefault(genre, 0) + play);
playsMap.putIfAbsent(genre, new ArrayList<>());
playsMap.get(genre).add(new int[]{i, play});
}
// 각 장르의 음악을 재생수로 내림차순 정렬한다.
for (Map.Entry<String, List<int[]>> entry : playsMap.entrySet()) {
entry.getValue().sort((s1, s2) -> {
if (s1[1] != s2[1]) {
return Integer.compare(s2[1], s1[1]);
} else {
return Integer.compare(s1[0], s2[0]);
}
});
}
// 각 장르의 총 재생수를 내림차순으로 정렬한다.
List<Map.Entry<String, Integer>> genresList = new ArrayList<>(genresMap.entrySet());
genresList.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
// 각 장르의 재생수 1,2위를 수록한다.
List<Integer> result = new ArrayList<>();
for (int i=0; i<genresList.size(); i++) {
Map.Entry<String, Integer> entry = genresList.get(i);
String genre = entry.getKey();
List<int[]> playList = playsMap.get(genre);
for (int j = 0; j < Math.min(2, playList.size()); j++) {
result.add(playList.get(j)[0]);
}
}
return result.stream().mapToInt(i -> i).toArray();
}
}
Java
복사
로직은 생각했는데 구현이 어려웠다.
•
Map → List로 변환한뒤 정렬하는 람다함수를 구현하는 방법을 몰라서 검색을 진행했다.
•
문제를 제대로 읽지 않아 장르에서 상위 2개가 아닌, 상위 장르 2개의 음악을 초기에 가져왔다.
•
List → 배열변환은 꼭 기억해두자.
다른사람 풀이
NOTE
public class Solution {
public class Music implements Comparable<Music>{
private int played;
private int id;
private String genre;
public Music(String genre, int played, int id) {
this.genre = genre;
this.played = played;
this.id = id;
}
@Override
public int compareTo(Music other) {
if(this.played == other.played) return this.id - other.id;
return other.played - this.played;
}
public String getGenre() {return genre;}
}
public int[] solution(String[] genres, int[] plays) {
return IntStream.range(0, genres.length)
.mapToObj(i -> new Music(genres[i], plays[i], i))
.collect(Collectors.groupingBy(Music::getGenre))
.entrySet().stream()
.sorted((a, b) -> sum(b.getValue()) - sum(a.getValue()))
.flatMap(x->x.getValue().stream().sorted().limit(2))
.mapToInt(x->x.id).toArray();
}
private int sum(List<Music> value) {
int answer = 0;
for (Music music : value) {
answer+=music.played;
}
return answer;
}
}
Java
복사
스트림 사용코드
•
스트림을 정말로 잘쓰는 코드다. groupingBy를 적극적으로 활용해 Map으로 사용하는 방식을 잘 알아두면 좋을것 같다.
•
이외에도 우선순위 큐 방식도 있긴하던데, 2개의 Map을 사용한 방법이 정석같아 따로 가져오진 않았다.