[java] 프로그래머스 - 베스트앨범
업데이트:
문제
프로그래머스-베스트앨범
장르와 재생횟수를 가지고 장르별로 가장 많이 재생된 노래를 두 곡씩 모아 인덱스를 리턴하는 문제
장르 총 재생 수, 각 장르 내의 재생 횟수 많은 순으로 2곡씩 뽑아 앨범을 만든다.
- 예시
장르 : 클래식, 팝, 클래식, 클래식, 팝
재생 횟수 : 500, 600, 150, 800, 2500
클래식은 총 1450회 재생, 팝은 총 3100회 재생
-> 팝먼저 수록, 팝 중에서 재생 수가 많은 2곡 + 클래식 중에서 재생수가 많은 2곡
4,1,3,0 순으로 앨범 생성 - 주의
- 장르 속한 곡이 1개라면 1개 곡만 선택
- 모든 장르는 재생 횟수가 다름
풀이
1) 장르, 장르 총 재생 횟수, 곡(song) 리스트를 재생횟수 순으로 저장하는 Songs클래스 생성, Songs객체 하위로 들어갈 인덱스와 재생횟수를 저장하는 song클래스 생성
2) 장르와 인덱스를 담을 해쉬맵 생성 (keys),
Songs객체를 담는 어레이리스트 생성 (songs)
3) 반복문 돌면서 입력받은 곡 정보를 순환
3-1) 맵에 해당 장르가 있으면 songs의 인덱스번째 객체에 재생횟수 추가하고, 하위 곡으로 추가
3-2) 없는 경우, keys에 장르 이름, songs의 다음 인덱스로 put해줌
마찬가지로 songs의 인덱스번째에 객체 생성 후 재생횟수와 장르 이름을 담음
4) 반복문 순환 후 songs의 전체 재생횟수에 따라 정렬한다
5) songs를 돌면서 하위곡이 1개 이하면 정답에 1개 곡의 인덱스 추가
2개 이상이면 재생횟수 순으로 상위 2개 곡의 인덱스를 정답에 추가
소스코드
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
int t = 0;
ArrayList<Songs> songs = new ArrayList<>();
HashMap<String, Integer> keys = new HashMap<>();
for (int i = 0; i < genres.length; i++) {
if (keys.containsKey(genres[i])) {
int idx = keys.get(genres[i]);
Songs s = songs.get(idx);
s.cnt += plays[i];
s.songList.add(new song(i, plays[i]));
} else {
keys.put(genres[i], songs.size());
Songs s = new Songs(genres[i], plays[i]);
s.songList.add(new song(i, plays[i]));
songs.add(s);
}
}
songs.sort(new Comparator<Songs>() {
@Override
public int compare(Songs o1, Songs o2) {
// TODO Auto-generated method stub
return o2.cnt - o1.cnt;
}
});
for (int i = 0; i < songs.size(); i++) {
if(songs.get(i).songList.size()<2) {
t+=songs.get(i).songList.size();
}else {
t+=2;
}
}
int answer[] = new int[t];
int idx = 0;
for (int i = 0; i < songs.size(); i++) {
int size = songs.get(i).songList.size();
if(size>2)
size = 2;
for (int j = 0; j < size; j++) {
answer[idx++] = songs.get(i).songList.poll().idx;
}
}
return answer;
}
}
class Songs {
String genre;
int cnt;
PriorityQueue<song> songList = new PriorityQueue<>();
public Songs(String genre, int cnt) {
super();
this.genre = genre;
this.cnt = cnt;
}
@Override
public String toString() {
return "Songs [genre=" + genre + ", cnt=" + cnt + ", " + songList;
}
}
class song implements Comparable<song> {
int idx;
int plays;
public song(int idx, int plays) {
super();
this.idx = idx;
this.plays = plays;
}
@Override
public int compareTo(song o) {
// TODO Auto-generated method stub
if (this.plays == o.plays) {
return this.idx - o.idx;
}
return o.plays - this.plays;
}
}
다른 사람의 코드
IntStream은 무엇일까..
굉장히 파이써닉한 코드같은 자바코드다
댓글 중에 실행시간이 오래걸려 비효율적이라고 하지만
이런식으로 코드를 짤 수 있다는 것을 공부하는데 좋은 코드라고 했다.
나름 자바를 배웠는데도 무슨 의미인지 코드가 어렵다 ㅠㅠ
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
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;
}
}
댓글남기기