https://programmers.co.kr/learn/courses/30/lessons/42579
방법1 : Comparable 활용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
import java.util.*;
class Solution {
public class Music implements Comparable<Music> {
private int played;
private String genre;
private int index;
public Music(String genre, int played, int index) {
this.genre = genre;
this.played = played;
this.index = index;
}
@Override
public int compareTo(Music other) {
// 많이 재생된 장르를 먼저
int iOrder = CountMap.get(other.genre) - CountMap.get(this.genre);
if (iOrder != 0) {
return iOrder;
}
// 많이 재생된 노래를 먼저
if (iOrder == 0) {
return other.played - this.played;
}
// 고유 번호가 낮은 노래를 먼저
if (iOrder == 0) {
return this.index - other.index;
}
return iOrder;
}
}
Map<String, Integer> CountMap;
public int[] solution(String[] genres, int[] plays) {
CountMap = new HashMap<String, Integer>();
List<Music> infoList = new ArrayList<Music>();
// infoList : 노래 정보
// CountMap : 장르별 재생횟수 카운트
for (int i = 0; i < genres.length; i++) {
String genre = genres[i];
int played = plays[i];
Music music = new Music(genre, played, i);
infoList.add(music);
if (CountMap.containsKey(genre)) {
CountMap.put(genre, CountMap.get(genre) + played);
continue;
}
CountMap.put(genre, played);
}
// 주어진 조건대로 정렬
Collections.sort(infoList);
// 장르별 최대 2곡씩 선택
return pickSongs(infoList);
}
private int[] pickSongs(List<Music> infoList) {
int count = 1;
for (int i = 1; i < infoList.size(); i++) {
Music music1 = infoList.get(i);
Music music2 = infoList.get(i - 1);
if (count >= 2) {
if (music1.genre.equals(music2.genre)) {
infoList.remove(i);
i--;
continue;
}
count = 0;
}
if (!music1.genre.equals(music2.genre)) {
count = 1;
continue;
}
if (count < 2) {
count++;
}
}
// 리스트 -> 배열
int[] answer = new int[infoList.size()];
for (int i = 0; i < answer.length; i++) {
answer[i] = infoList.get(i).index;
}
return answer;
}
}
Colored by Color Scripter
|
방법2: Comparator 활용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
import java.util.*;
import java.util.Map.Entry;
class Solution {
public int[] solution(String[] genres, int[] plays) {
Map<String, Integer> CountMap = new HashMap<String, Integer>();
Map<Integer, Integer> playsMap = new HashMap<Integer, Integer>();
// playsMap : plays 배열 -> 맵
// CountMap : 장르별 재생횟수 카운트
for (int i = 0; i < genres.length; i++) {
String key = genres[i];
playsMap.put(i, plays[i]);
if (CountMap.containsKey(key)) {
CountMap.put(key, CountMap.get(key) + plays[i]);
continue;
}
CountMap.put(key, plays[i]);
}
// 주어진 조건대로 정렬
List<Map.Entry<Integer, Integer>> playsList = new LinkedList<>(playsMap.entrySet());
Collections.sort(playsList, new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
// 많이 재생된 장르를 먼저
int iOrder = CountMap.get(genres[o2.getKey()]) - CountMap.get(genres[o1.getKey()]);
// 많이 재생된 노래를 먼저
iOrder = (iOrder == 0) ? o2.getValue() - o1.getValue() : iOrder;
// 고유 번호가 낮은 노래를 먼저
iOrder = (iOrder == 0) ? o1.getKey() - o2.getKey() : iOrder;
return iOrder;
}
});
// 장르별 최대 2곡씩 선택
int count = 0;
List<Integer> liAnswer = new ArrayList<Integer>();
Iterator<Map.Entry<Integer, Integer>> iter = playsList.iterator();
while (iter.hasNext()) {
Map.Entry<Integer, Integer> entry = iter.next();
if (count >= 2) {
if (genres[liAnswer.get(liAnswer.size() - 1)].equals(genres[entry.getKey()])) {
continue;
}
count = 0;
}
if (liAnswer.size() > 0
&& !genres[liAnswer.get(liAnswer.size() - 1)].equals(genres[entry.getKey()])) {
count = 0;
}
if (count < 2) {
liAnswer.add(entry.getKey());
count++;
}
}
// 리스트 -> 배열
int[] answer = new int[liAnswer.size()];
for (int i = 0; i < answer.length; i++) {
answer[i] = liAnswer.get(i);
}
return answer;
}
}
Colored by Color Scripter
|
속도차이는 크게 나지 않는다.
하지만 방법1이 훨씬 깔끔하다.
정렬이 포인트인 문제였는데,
이번 문제로 어떨 때 Comparable과 Comparator을 쓰는지 감을 잡았다.
TIP1
정보가 3개 이상 쓰일 때는 따로 클래스를 만들어서 담아주자
이 문제에서 노래 하나에 연관된 정보는 인덱스값, 장르, 플레이횟수로 총 3개이다.
이것을 map과 주어진 배열로만 푼게 방법 2번인데,
코드가 상당히 지저분해졌다.
방법1처럼 <노래 = Music 객체> 이렇게 만들어서
리스트에 담아주니 훨씬 깔끔해졌다.
장르별 총 플레이 횟수도 Music 객체에 담을 수도 있었겠지만,
정보의 완결성(?)을 침해하고 2중 for문이 필요할 것 같아서
장르별 플레이 횟수는 따로 HashMap으로 담았다.
그리고 어쨌든 Hash 문제이니깐...
TIP2
Comparable과 Comparator 구현 방식 차이
Comparable방식도 compareTo 메소드를 오버라이드 해서 구현한다.
이 때, 전역변수 this = o1, 매개변수 other = o2로 생각해서 순서를 구현하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
//1. Comparable
public class Music implements Comparable<Music> {
@Override
public int compareTo(Music other) {
// 많이 재생된 장르를 먼저
int iOrder = CountMap.get(other.genre) - CountMap.get(this.genre);
if (iOrder != 0) {
return iOrder;
}
// 많이 재생된 노래를 먼저
if (iOrder == 0) {
return other.played - this.played;
}
// 고유 번호가 낮은 노래를 먼저
if (iOrder == 0) {
return this.index - other.index;
}
return iOrder;
}
}
//2. Comparator
Collections.sort(playsList, new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
// 많이 재생된 장르를 먼저
int iOrder = CountMap.get(genres[o2.getKey()]) - CountMap.get(genres[o1.getKey()]);
// 많이 재생된 노래를 먼저
iOrder = (iOrder == 0) ? o2.getValue() - o1.getValue() : iOrder;
// 고유 번호가 낮은 노래를 먼저
iOrder = (iOrder == 0) ? o1.getKey() - o2.getKey() : iOrder;
return iOrder;
}
});
Colored by Color Scripter
|
'Algorithm > 프로그래머스' 카테고리의 다른 글
[프로그래머스]스택/큐 : 주식가격 (level 2) (c++) (0) | 2020.04.28 |
---|---|
[프로그래머스][2019 카카오 개발자 겨울 인턴십] 크레인 인형뽑기 게임 (level 1)(c++) (0) | 2020.04.28 |
[프로그래머스]해시 : 위장 (level 2) (java, c++) (0) | 2019.12.17 |
[프로그래머스][2018 KAKAO BLIND RECRUITMENT] [1차] 다트 게임 (level 1) (0) | 2019.12.10 |
[프로그래머스][2019 KAKAO BLIND RECRUITMENT] 실패율 (level 1) (0) | 2019.12.10 |
댓글