알고리즘/PS - 프로그래머스

[프로그래머스 - Java] 베스트앨범

excited-hyun 2021. 9. 1. 18:51
반응형

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

 

코딩테스트 연습 - 베스트앨범

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

programmers.co.kr

 

풀이

 

이 문제에선 속한 음악의 재생수가 가장큰 장르부터 answer에 넣어주며, 해당 장르 안에서는 가장 많이 재생된 2곡을 순서대로 넣어줍니다. 만약 재생횟수가 동일하다면 인덱스가 작은것을 먼저 넣어주는 문제입니다.

 

  1. 우선 각 장르별로 총 재생수를 구합니다
    • HashMap을 이용해 key는 장르, value는 총 재생 수로 하여 중복없이 총합이 구해지도록 합니다
  2. HashMap을 value값(총 재생 수)를 기준으로 내림차순으로 key 값만을 뽑아 ArrayList에 저장합니다.
  3. ArrayList의 있는 장르 순서대로 해당 장르에서 가장 많이 재생된 2곡을 넣어주어야 합니다.
    • 이 때 answer배열에 바로 넣을 수는 없습니다. (어떤 장르는 1곡만 있을 수 있기 때문)
    • 따라서 임의로 사용할 ArrayList를 만들어 저장해두고 모두 완료 후 answer의 크기를 선언한 뒤 옮겨주어야합니다.
  4. 가장 많이 재생된 2곡을 뽑는 방식은 다음과 같습니다.
    1. genres 배열을 탐색하면서 현재 진행중인 장르와 같은 장르를 찾습니다. (firstMax,secondMax = 0으로, firstIdx,secondIdx =-1로 초기화)
    2. 같은 장르를 발견한 경우 해당 index에 해당하는 plays의 값과 기존의 가장 큰 재생수(firstMax)를 비교합니다.
      1. firstMax보다 큰 경우 : secondMax에 firstMax를 넣고 FirstMax에 plays[index]를 넣어줍니다. (인덱스도 함께 업데이트 해줌)
      2. firstMax보다 작은 경우: secondMax와 비교해 secondMax보다 큰 경우 secondMAx에 plays[index]를 넣고 마찬가지로 인덱스도 업데이트 합니다.
    3. genres배열 탐색이 완료되면 secondIdx의 값이 -1인지 확인합니다. (해당 장르에 한곡만 존재)
    4. -1이 아닌 경우 ArrayList에 firstIdx와 secondIdx를 차례로 넣고, -1인 경우엔 firstIdx만 넣습니다.
  5. 모든 장르에 대해 2곡뽑기를 완료하면 ArrayList의 size와 동일한 answer배열을 만들어 값을 옮겨줍니다.

 

import java.util.*;

class Solution {
    public int[] solution(String[] genres, int[] plays) {
        
        HashMap <String, Integer> m1 = new HashMap<>();
        int size = plays.length;
        
        //장르별 재생 수
        for(int i=0; i<size; i++){
            String g = genres[i];
            int p = plays[i];
            //이미 map에 추가된 장르
            if(m1.containsKey(g)){
                int cnt = m1.get(g);
                m1.put(g, cnt+p);
            }
            //아직 추가되지 않음
            else{
                m1.put(g, p);
            }
        }
        
        //장르에 속한 곡이 하나일 수도 있어서 answer를 배열로 선언해 사용불가
        ArrayList<Integer> temp = new ArrayList<Integer>();  
        
        //value기준으로 내림차순 정렬
        List<String> keyList = new ArrayList<>(m1.keySet());
        Collections.sort(keyList, (o1,o2)->(m1.get(o2).compareTo(m1.get(o1))));
        
        for(int i=0; i<keyList.size(); i++){
            String g = keyList.get(i);
            int firstMax = 0;
            int secondMax = 0;
            int firstIdx = -1;
            int secondIdx = -1;
            for(int j=0; j<size; j++){
                if(genres[j].equals(g)){
                    //이번꺼가 제일 큼
                    if(firstMax < plays[j]){
                        //첫번째를 두번째에 넣고 이번꺼를 첫번째에 넣음
                        secondMax = firstMax;
                        firstMax = plays[j];
                        secondIdx = firstIdx;
                        firstIdx = j;
                    }
                    //제일 큰거보단 작음
                    else {
                        //두번째 보다 큼
                        if(secondMax < plays[j]){
                            //두번째에 넣어줌
                            secondMax = plays[j];
                            secondIdx = j;
                        }
                        //두번째 보다 작으면 그냥 넘어감
                    }
                } 
            }
            //속한 곡이 하나
            if(secondIdx == -1){
                temp.add(firstIdx);
            }
            //둘이상
            else{
                temp.add(firstIdx); 
                temp.add(secondIdx);
            }
        }
        
        //answer 배열에 ArrayList값 옮기기
        int[] answer = new int[temp.size()];
        for(int i=0; i<temp.size(); i++){
            answer[i] = temp.get(i);
        }
        
        return answer;
    }
}

 

 

 

728x90
반응형