[해시] 베스트앨범

2 minute read


문제

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

  • 속한 노래가 많이 재생된 장르를 먼저 수록한다.

  • 장르 내에서 많이 재생된 노래를 먼저 수록한다.

  • 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록한다.


제한사항

  • genres[i]는 고유번호가 i인 노래의 장르이다.

  • plays[i]는 고유번호가 i인 노래가 재생된 횟수이다.

  • 장르 종류는 100개 미만이다.

  • 장르에 속한 곡이 하나라면, 하나의 곡만 선택한다.

  • 모든 장르는 재생된 횟수가 다르다.


나의 풀이

입력받는 데이터는 문자열 장르, 정수값 재생 횟수이다.

  • 입력 데이터를 해시로 만들고 키값을 할당한다.

  • 정렬을 통해 원하는 값을 도출해낸다.

#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>

using namespace std;

// 정렬는데 사용하는 기준 함수
bool SortSecCol(const vector<int>& v1, const vector<int>& v2)
{
    return v1[0] > v2[0];
}

bool SortSecCol2(const pair<int, int>& v1, const pair<int, int>& v2)
{
    return v1.first > v2.first;
}

vector<int> solution(vector<string> genres, vector<int> plays) {
    vector<int> answer;
    // 방법
    // 인풋 데이터를 묶는다.
    // 같은 장르의 곡들의 플레이 횟수 총합 계산
    // 총 횟수 내림차순 정렬, 이 정보로 앨범 구성
    
    // 데이터 정리
    // 곡 장르, 각 재생 횟수, 고유 키 정보 저장
    unordered_map<string, vector<pair<int, int>>> inputData;
    // 장르별 재생 횟수 합계
    unordered_map<string, int> totalPlay;

    for (int i = 0; i < genres.size(); i++) {
        inputData[genres[i]].push_back(make_pair(plays[i], i));
        totalPlay[genres[i]] += plays[i];
    }

    // 총 재생 횟수 내림차순 정렬을 위한 벡터
    vector<int> v;

    for (auto e : totalPlay) {
        v.push_back(e.second);
    }

    // 내림차순 정렬
    sort(v.begin(), v.end(), greater<int>());

    // 앨범 채우기
    // 정렬된 총 재생 횟수를 기준으로 장르를 비교하고 모든 정보가 담긴 해시에서 키값을 꺼내온다.
    for (int j = 0; j < v.size(); j++) {
        // 장르를 저장할 변수
        string gerne;
       
        // 장르의 총 재생 횟수 비교하기위한 반복자
        auto iter = totalPlay.begin();
        
        // 총 재생 횟수 순회 
        for (iter = totalPlay.begin(); iter != totalPlay.end(); iter++) {
            
            // 총 재생 횟수 같은 값 비교
            if (iter->second == v[j]) {
                // 해당 장르 값을 저장
                gerne = iter->first;
                
                // 모든 정보가 저장된 해시에서 장르 문자열을 통해 정보를 가져온다.
                auto tmp = inputData[gerne];
                
                // 가져온 장르의 각 재생 횟수 내림차순으로 정렬
                sort(tmp.begin(), tmp.end(), &SortSecCol2);
                
                // 앨범에 정보 저장하기
                // 곡이 하나일 때는 하나만, 두 개 상이라면 두개까지만 정보 저장
                if (tmp.size() < 2) {
                    answer.push_back(tmp[0].second);
                }
                else {
                    answer.push_back(tmp[0].second);
                    answer.push_back(tmp[1].second);
                }
            }
        }
    }
    return answer;
}

필요한 값을 찾고 정렬하는 부분에서 상당히 거슬리게 처리를 해버렸다.

sort(tmp.begin(), tmp.end(), &SortSecCol2);

map을 써서 정렬된 상태의 해시를 사용했어도 될 것 같다.

  • unordered_map 해시 정렬하는 방법 찾아보기