문제

스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.

  1. 속한 노래가 많이 재생된 장르를 먼저 수록합니다.
  2. 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
  3. 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.

노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요.

 

제한사항

  • genres[i]는 고유번호가 i인 노래의 장르입니다.
  • plays[i]는 고유번호가 i인 노래가 재생된 횟수입니다.
  • genres와 plays의 길이는 같으며, 이는 1 이상 10,000 이하입니다.
  • 장르 종류는 100개 미만입니다.
  • 장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.
  • 모든 장르는 재생된 횟수가 다릅니다.

나의 코드

 

import java.util.*;


public class BestAlbum {
	
	public static int[] solution(String[] genres, int[] plays) {
		
		HashMap<String, Integer> hash1 = new HashMap<>();
		for(int i=0; i<genres.length; i++) {
			hash1.put(genres[i], hash1.getOrDefault(genres[i], 0) + plays[i]);
		}
		
		List<Integer> sortP = new ArrayList<>();
		for(int gen : hash1.values()) {
			sortP.add(gen);
		}
		Collections.sort(sortP); Collections.reverse(sortP);
		
		List<String> sortG = new ArrayList<>();
		for(int s : sortP) {
			sortG.add(getKey(hash1, s));
			hash1.remove(getKey(hash1, s));
		}
		
		HashMap<String, Integer> hash2 = new HashMap<>();
		for(int i=0; i<genres.length; i++) {
			hash2.put(genres[i]+i, plays[i]);
		}
		
		List<String> keys = new ArrayList<>(hash2.keySet());
		Collections.sort(keys);
		
		HashMap<String, Integer> hash3 = new LinkedHashMap<>();
		for(String keysS : keys) {
			hash3.put(keysS, hash2.get(keysS));
		}
		
		List<Integer> list = new ArrayList<>();
		for(int pl : plays) {
			list.add(pl);
		}
		Collections.sort(list); Collections.reverse(list);
		
		int cnt = 0;
		String temp = sortG.get(0);
		List<Integer> solve = new ArrayList<>();
		for(String sg : sortG) {
			if(!temp.equals(sg)) cnt=0;
			for(int l : list) {
				if(cnt==2) {
					cnt = 0;
					break;
				}
				for(String ha : hash3.keySet()) {
					if(cnt==2) break;
					if(ha.indexOf(sg) >= 0 && hash3.get(ha) == l) {
						cnt++;
						solve.add(Integer.parseInt((ha.replace(sg, ""))));
						temp = sg;
					}
				}
				
			}
		}
		
		int[] answer = new int[solve.size()];
		for(int i=0; i<answer.length; i++) {
			answer[i] = solve.get(i);
		}
		return answer;
	}
	
	public static <K, V> K getKey(Map<K, V> map, V value) {
        for (K key : map.keySet()) { 
            if (value.equals(map.get(key))) {
                return key;
            }
        }
        return null;
   }

}

 

나의 풀이

우선.. 코드가 생각보다 길게 나왔다. 정답을 제출해보니 효율성은 안 따지고 정답만 따지는 걸 보니 길어도 상관없는 모양이다.

그래도 나름 열심히 생각하면서 짜봤다. 풀이로 들어가 보자.

1. getOrDefault 를 사용해서 장르별로 플레이 횟수를 다 합쳐서 hash1에 저장한다.

2. hash1 HashMap 에 저장되어있는 value들을 sortP ArrayList에 저장한다.

3. sortP ArrayList 를 오름차순 정렬하고, 곧바로 역순으로 정렬한다.

4. sortG에 내가 만든 getKey 를 사용하여 sortP에 저장된 value에 해당하는 Key를 저장한다. 

제한 사항에 모든 장르는 재생 횟수가 다르다고 했지만 혹시 몰라 같은 경우를 대비해 remove를 해주었다.

5. hash2 HashMap에는 key에 장르 value에 플레이를 넣지만 장르는 중복되므로 식별성으로 for에 사용된 i를 추가

6. keys ArrayList 에는 hash2 HashMap에 key들을 모두 저장 후 오름차순 정렬

7. hash3 LinkedHashMap에는 정렬된 key들을 key로 value에는 hash2.get(key)로 저장한다.

HashMap은 순서가 정해져 있지 않아 랜덤 해서 값들이 호출된다. 그래서 순서대로 적용되는 LinkedHashMap 사용

8. list ArrayList에는 재생 횟수를 저장, 이것도 마찬가지로 오름차순 정렬 후, 역 정렬

9. 저장 횟수를 저장할 cnt(int)변수, 이전의 장르를 저장할 temp(String)변수를 생성, temp에는 sortG의 첫 번째 값 저장

sortG는 정렬된 장르 ArrayList로 뒤에서 if비교문이 있기 때문에 첫 번째 값은 필수로 들어가야 한다.

10. 첫번째 for문에서는 sortG에 저장된 값을 돌린다.

11. 두 번째 for문으로 넘어가기 전 sortG의 값과 temp의 값이 다르면 cnt를 0으로 초기화시킨다.

한 장르에 플레이 횟수가 하나만 있을 수 있기 때문

12. 두 번째 for문에서는 list에 저장된 값을 돌린다. 

13. 세 번째 for문으로 넘어가기 전 cnt가 2라면 cnt를 초기화시키며 두 번째 for문으로 break시킨다.

한 장르에 같은 재생 횟수가 있을 수 있기 때문

14. 세 번째 for문에서는 hash3의 key들을 keySet으로 불러 돌린다.

15. 들어가자마자 if문으로 cnt가 2라면 세번째 for문을 break 시킨다.

한 장르당 두 개씩만 저장해야하기 때문

16. 15번 if문을 통과했다면 14번에서 불러온 값들은 이전 식별성을 위해 i++를 붙여놨기 때문에 indexOf로 포함되어있는지 확인

17. && hash3 HashMap에서 세 번째 for문의 key값에 해당하는 값이 두 번째 for문에 있는 list에 들어있는 값과 같으면 통과

18. 여기까지 들어오면 값이 실제로 저장된다는 것이므로 cnt++

19. index를 저장하는 것이 문제이기 때문에 replace로 첫 번째 for문으로 돌린 값 삭제 ( 그 후 replace된 값을 solve ArrayList에 저장 )

20. 이전 값을 저장하는 temp에 첫번째 for문으로 돌린 값 저장 ( 첫번째 for문으로 돌아갈 때 11번으로 간다 )

21. 정답을 저장할 answer Array를 solve.size의 크기로 선언

22. for문을 통해 solve에 저장된 값 answer에 저장

23. 그리고 answer return

 

+ Recent posts