[JAVA/프로그래머스] 해시: 베스트앨범

👀 문제

https://programmers.co.kr/learn/courses/30/lessons/42579

👊 도전

1. 설계

  1. 노래를 Music형으로 배열에 저장한다.
  2. 해시맵을 이용해 장르별 노래 재생 횟수를 구한 후, 재생 횟수에 따라 내림차순 정렬한다.
  3. 가장 많이 재생된 장르부터 각 장르별 많이 재생된 두 곡의 인덱스를 저장한다.

2. 구현

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
import java.util.*;
import java.util.Map.Entry;
/**
 *
 * @author HEESOO
 *
 */
import java.util.*;
import java.util.Map.Entry;
class Solution {
    public int[] solution(String[] genres, int[] plays) {
        Music[] music=setMusic(genres, plays);
		String[] sortGenres=getGenres(genres, plays);
		ArrayList<Integer> list=new ArrayList<>();
		for(String sg:sortGenres) {
			ArrayList<Music> temp=new ArrayList<>();
			for(Music m:music) {
				if(m.genres.equals(sg)) {
					temp.add(m);
				}
			}
			Collections.sort(temp);
			for(int i=0;i<2;i++) {
				if(i<temp.size()) list.add(temp.get(i).idx);
			}
		}
		
		int[] answer=new int[list.size()];
		for(int i=0;i<list.size();i++) {
			answer[i]=list.get(i).intValue();
		}
		
		return answer;
	}
	
	public Music[] setMusic(String[] genres, int[] plays) {
		int size=genres.length;
		Music[] musics=new Music[size];
		for(int i=0;i<size;i++) 
			musics[i]=new Music(genres[i], i, plays[i]);
		
		return musics;
	}
	
	public String[] getGenres(String[] genres, int[] plays) {
		int size=genres.length;
		HashMap<String, Integer> map=new HashMap<>();
		for(int i=0;i<size;i++) {
			String key=genres[i];
			int value=plays[i];
			map.put(key, map.getOrDefault(key, 0)+value);
		}
		
		TreeMap<Integer, String> tree=new TreeMap<>(Collections.reverseOrder());
		for(Entry<String, Integer> entry:map.entrySet()) {
			tree.put(entry.getValue(), entry.getKey());
		}
		
		String[] result=new String[tree.size()];
		int idx=0;
		for(Entry<Integer, String> entry:tree.entrySet()) {
			result[idx++]=entry.getValue();
		}
		
		return result;
	}
	
	
}

class Music implements Comparable<Music>{
	String genres;
	int idx;
	int times;
	public Music(String g, int t) {
		this.genres=g;
		this.times=t;
	}
	public Music(String g, int i, int t) {
		this.genres=g;
		this.idx=i;
		this.times=t;
	}
	
	@Override
	public int compareTo(Music m1) {
		if(this.times<m1.times) return 1;
		else if(this.times==m1.times) return 0;
		else return -1;
	}
}

3. 결과

실행결과 🤟 성공 🤟

4. 설명

  1. genres와 plays를 이용해 Music형으로 노래를 저장한다
    • setMusic() 메소드로 구현하였다.
    • Music 클래스를 선언한다. genres는 장르, idx는 고유 인덱스 번호, times는 재생 횟수이다.
    • 생성자는 파라미터를 두 개 가지는 것과 세 개 가지는 것이 있다. 첫 번째는 장르별 가장 많이 재생된 것을 구할 때 사용하기 위함이고, 두 번째는 노래 한 곡을 저장하는 생성자이다. compareTo()는 Music형 클래스를 정렬할 때 재생 횟수에 따라 내림차순 정렬한다.
    • setMusic()에서 i번째 노래를 Music형으로 객체를 생성해 배열에 저장한 후 리턴한다.
  2. 가장 많이 재생된 장르순을 구한다
    • 해시맵을 통해 장르별 총 재생 횟수를 구한다. getOrDefault()를 통해 key에 대해 기존 value가 없으면 0을 주어 현재 value를 더한다.
    • 해시맵으로 장르별 총 재생 횟수를 구하면, TreeMap을 이용해 재생 횟수 기준 내림차순 정렬한다. 해시맵에서는 정렬이 불가하기 때문에 TreeMap을 사용하며, key 기준으로 정렬하기 때문에 해시맵에서 TreeMap으로 값을 전달 및 저장할 때 key와 value 순서를 바꾼다. key는 중복되면 안되는데, 문제 조건에서 장르별 총 재생 횟수는 중복되지 않는다고 했으므로 데이터가 손실되지 않는다. 내림차순 정렬을 위해 Collections.reverseOrder()을 이용한다.
    • TreeMap에 해시맵 값을 넣으면 재생 횟수 내림차순으로 정렬되고, 하나씩 빼서 String[]에 장르를 저장, 리턴한다.
  3. 장르별 가장 많이 재생한 노래를 두 개 저장한다
    • ArrayList list에 장르 순서대로 인덱스를 저장한다.
    • 정렬된 장르 sortGenres[]에서 순서대로 장르를 뽑고, music[]을 모두 체크하며 특정 장르를 모두 뽑아 temp에 저장한 후, Collections.sort()로 재생 횟수 기준 내림차순 정렬한다. temp에서 정렬된 기준으로 인덱스를 최대 2개 뽑아 list에 저장한다.
    • list는 Integer형이고, 리턴은 int형 배열이므로 형변환하여 리턴한다.

👏 해결 완료!