[Java] 프로그래머스 Hash > 베스트앨범 자바

: ) YOUNG·2022년 4월 15일
2

알고리즘

목록 보기
98/422
post-thumbnail

프로그래머스 > Hash > 베스트앨범
https://programmers.co.kr/learn/courses/30/lessons/42579


문제

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

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

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


제한사항

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

입출력 예

genresplaysreturn
["classic", "pop", "classic", "classic", "pop"][500, 600, 150, 800, 2500][4, 1, 3, 0]

생각하기

HashMap과 ArrayList자료구조 2가지를 사용해서 풀었다.

동작

    	HashMap<String, Integer> map = new HashMap<>();
    	ArrayList<String> genre_list = new ArrayList<>();

    	int genres_len = genres.length;
    	for(int i=0; i<genres_len; i++) {

    		if( !map.containsKey(genres[i]) ) {
    			genre_list.add(genres[i]);
    		}	
    		map.put(genres[i], map.getOrDefault(genres[i], 0)+plays[i]);
    	}

먼저 genres[] 배열에 어떤 장르별 총 재생횟수를 파악하기 위해 HashMap을 사용한다.

그리고 map에 포함되지 않은 장르는 genre_list에 넣는다
장르가 중첩되지 않도록 하나만 들어 갈 수 있도록 만든다.

    	// 장르만 담긴 genre_list를 재생횟수가 높은 순으로 정렬
    	Collections.sort(genre_list, (o1, o2) -> map.get(o2) - map.get(o1));

그리고 각 장르의 종류가 들은 genre_list에서 각 장르별 전체 재생 횟수가 가장 많은 순서대로 정렬하기 위해 Collections.sort()를 사용한다.

    	ArrayList<Music> result = new ArrayList<>();
    	for(String genr : genre_list) {
    		ArrayList<Music> list = new ArrayList<>();

    		for(int i=0; i<genres_len; i++) {
    			if(genres[i].equals(genr)) {
    				list.add(new Music(genr, i, plays[i]));
    			}
    		}
    		Collections.sort(list, (o1, o2) -> o2.Streaming - o1.Streaming);

    		// 장르에 포함된 곡을 2개 result에 담기
    		result.add(list.get(0));
   		
    		// 장르에 포함된 곡이 1개 일 경우 하나만 포함
    		if(list.size() > 1) {
    			result.add(list.get(1));
    		}
    	}

결과 값을 담을 result Music객체형 new ArrayList<Music>을 생성해준다.

Music 객체는

  • 장르이름 = genre_name
  • 각 노래의 고유 번호 = id
  • 재생횟수 = Streaming
    이렇게 3가지로 구성되어 있다.

genre_list에서 나오는 각 장르의 이름 값인 genr의 값을 기준으로
genres의 배열에 있는 값과 genr가 일치하는 값을 list에 Music객체형으로 넣어준다.

Ex) 우리가 아까 gener_list에서 정렬을 해준 상태이고, genre_list에서 pop이 가장 앞에 있으니까 pop이 가장 먼저 나오게 된다. genres[] 배열에서 pop과 같은 장르만을 list에 집어 넣는다ㅏ.

이렇게 하면 pop장르의 노래들만 genres[]배열에서 꺼내서 list에 넣을 수 있다.

다음이 classic 장르니까 classic 장르만 genres[] 배열에서 찾아서 list에 넣게 된다.

이렇게 하면 우리는 아까 미리 각 장르를 전체 재생횟수 순으로 미리 정렬을 해두었기 때문에 순서대로 result에 값을 넣어서 출력만 하면된다.

여기서 놓치면 안되는 부분은 문제에서 장르 내에서 곡이 하나 밖에 없을 때는 하나만 출력하라고 했을 때인데 이때는

    		if(list.size() > 1) {
    			result.add(list.get(1));
    		}

해당 조건문을 넣어서 list에 해당 장르가 한개이상인지 판단해서 result에 추가하면 된다.



TMI

베스트앨범 그렇게 하는 거 아닌데 쿠쿠



코드

import java.util.*;

class Solution {

	static class Music {
		String genre_name;
        int id;
		int Streaming;

		public Music(String genre_name, int id, int Streaming) {
			this.genre_name = genre_name;
			this.id = id;
			this.Streaming = Streaming; 
		}
	}

    public int[] solution(String[] genres, int[] plays) {
    	HashMap<String, Integer> map = new HashMap<>();
    	ArrayList<String> genre_list = new ArrayList<>();

    	int genres_len = genres.length;
    	for(int i=0; i<genres_len; i++) {

    		if( !map.containsKey(genres[i]) ) {
    			genre_list.add(genres[i]);
    		}	
    		map.put(genres[i], map.getOrDefault(genres[i], 0)+plays[i]);
    	}

    	// 장르만 담긴 genre_list를 재생횟수가 높은 순으로 정렬
    	Collections.sort(genre_list, (o1, o2) -> map.get(o2) - map.get(o1));

    	ArrayList<Music> result = new ArrayList<>();
    	for(String genr : genre_list) {
    		ArrayList<Music> list = new ArrayList<>();

    		for(int i=0; i<genres_len; i++) {
    			if(genres[i].equals(genr)) {
    				list.add(new Music(genr, i, plays[i]));
    			}
    		}
    		Collections.sort(list, (o1, o2) -> o2.Streaming - o1.Streaming);

    		// 장르에 포함된 곡을 2개 result에 담기
    		result.add(list.get(0));
   		
    		// 장르에 포함된 곡이 1개 일 경우 하나만 포함
    		if(list.size() > 1) {
    			result.add(list.get(1));
    		}
    	}
  	
   	
    	int result_size = result.size();
    	int arr[] = new int[result_size];
    	for(int i=0; i<result_size; i++) {
    		arr[i] = result.get(i).id;
    	}

    	return arr;
    }
}

0개의 댓글