쾌락없는 책임 (공부)/알고리즘 문제풀이

[Algorithm] 프로그래머스 베스트 앨범 - C++, map, unordered_map

허스크 2022. 5. 13. 13:08
반응형
 

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

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

programmers.co.kr

#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <map>
using namespace std;

bool cmp(const pair<string, int>& a, const pair<string, int>& b){
    return a.second > b.second;
}

vector<int> solution(vector<string> genres, vector<int> plays) {
    vector<int> answer;

    unordered_map<string, int> genresTimes;
    unordered_map<string, map<int, int>> musicInfo; // genres, index, playtimes

    // make unordered map
    for(int i = 0; i < genres.size(); i++){
        genresTimes[genres[i]] += plays[i];
        musicInfo[genres[i]][i] = plays[i];
    } 

    // find most played genres
    // and find most played music in that genres

    // 1. sort genres by played time
    vector<pair<string, int>> genresPlayTimes(genresTimes.begin(), genresTimes.end());
    sort(genresPlayTimes.begin(), genresPlayTimes.end(), cmp);

    for(int i = 0; i < genresPlayTimes.size(); i++){
        // search most played genres
        string curGenre = genresPlayTimes[i].first;
        
        // find two music in this genres
        for(int genCount = 0; genCount < 2; genCount++){
            int playTime = -1, index = -1;
            for(auto music : musicInfo[curGenre]){
                if(playTime < music.second){
                    playTime = music.second;
                    index = music.first;
                }
            }

            if(index == -1) continue;

            answer.push_back(index);
            musicInfo[curGenre].erase(index);
        }
    }

    return answer;
}

 이번에는 생각할게 좀 있는 문제였습니다.

 

 일단 unordered_map 을 2개 선언을 해 주는데 역할은 아래와 같습니다.

genresTimes
장르별 플레이타임 횟수를 저장
musicInfo
장르 내 음악들의 정보를 저장

 이중 musicInfo 안에는 unordered_map이 아닌 map이 들어가 있는데 이는 map 은 들어가면 key값을 기준으로 자동 정렬이 되어 이후 출력에서 인덱스가 빠른 순으로 보낼 수 있기 때문입니다.

bool cmp(const pair<string, int>& a, const pair<string, int>& b){
    return a.second > b.second;
}
...

// 1. sort genres by played time
    vector<pair<string, int>> genresPlayTimes(genresTimes.begin(), genresTimes.end());
    sort(genresPlayTimes.begin(), genresPlayTimes.end(), cmp);

 이후 genresTimes에 모든 데이터를 넣어둔 뒤 장르들을 전부 vector에 넣은 뒤 정렬을 해 줍니다. cmp 함수에서 왼쪽이 더 큰 경우로 해서 높은 값이 먼저 오게 오름차순으로 해 주시면 됩니다.

    for(int i = 0; i < genresPlayTimes.size(); i++){
        // search most played genres
        string curGenre = genresPlayTimes[i].first;
        
        // find two music in this genres
        for(int genCount = 0; genCount < 2; genCount++){
            int playTime = -1, index = -1;
            for(auto music : musicInfo[curGenre]){
                if(playTime < music.second){
                    playTime = music.second;
                    index = music.first;
                }
            }

            if(index == -1) continue;

            answer.push_back(index);
            musicInfo[curGenre].erase(index);
        }
    }

 이후 각 장르에서 가장 많이 들린 노래를 골라야 하는데 여기서 주의할 점이 각 장르에서 2개만 뽑아야 하는 것, 장르에 노래가 1개면 1개만 삽입해야 하는 것, 같은 재생수라면 인덱스 번호순으로 해야 한다는 것입니다.

 위 주의점들을 처리하기 위해서 for문은 각 장르에서 2번만 돌게 했으며 노래가 1개인 경우는 index == -1 을 체크해 처리했습니다. (index 값이 변경되지 않았다면 해당 장르에 남은 곡이 없다는 뜻) 그리고 인덱스 번호순은 따로 정렬을 두지 않고 unordered_map안에 unordered_map 대신 map을 넣어서 처리했습니다.

반응형