
별도의 클래스와 해당 클래스 객체 간 정렬 함수를 잘 정의하는 것이 중요한 문제이다.
import java.util.*;
class Song implements Comparable<Song> {
private final static Map<String, Integer> genreCount = new HashMap<>();
private String genre;
private int plays;
private int id;
public Song(String genre, int plays, int id) {
this.genre = genre;
this.plays = plays;
this.id = id;
genreCount.put(genre, genreCount.getOrDefault(genre, 0) + plays);
}
public String getGenre() {
return this.genre;
}
public int getId() {
return this.id;
}
@Override
public int compareTo(Song other) {
if (this.genre.equals(other.genre)) {
if (this.plays == other.plays) {
return this.id - other.id;
}
return other.plays - this.plays;
}
return genreCount.get(other.genre) - genreCount.get(this.genre);
}
}
class Solution {
public int[] solution(String[] genres, int[] plays) {
List<Song> songs = new ArrayList<>();
for (int i = 0; i < genres.length; i++)
songs.add(new Song(genres[i], plays[i], i));
Collections.sort(songs);
Map<String, Integer> addCount = new HashMap<>();
List<Integer> ids = new ArrayList<>();
for (Song s : songs) {
addCount.put(s.getGenre(), addCount.getOrDefault(s.getGenre(), 0) + 1);
if (addCount.get(s.getGenre()) <= 2)
ids.add(s.getId());
}
return ids.stream().mapToInt(i -> i).toArray();
}
}
Java에서 사용자 정의 정렬 함수를 정의하는 방법은 다양하지만, 내가 생각했을 때 가장 간단한 방법은 Comparable 클래스를 상속받아 compareTo 메서드를 재정의하는 것이다. 코드에서 보면 알 수 있듯이 this.x - other.x은 x에 대해 오름차순, other.x - this.x는 내림차순으로 정렬한다.
일단 데이터를 정렬해 두고 카운팅을 위해 Map(addCount)을 사용한다. 그 다음 id들을 순서대로 저장하면 된다. 마지막으로 List<Integer> 타입을 int[] 타입으로 변환해야 하는데, 그냥 toArray 메서드에 ids를 전달하면 Object[] 타입의 배열이 생성된다. 그래서 stream - mapToint - toArray 메서드 체인을 사용해야 한다. mapToInt의 인자로 람다 함수를 전달하는 것도 유의하자.