Algorithm

[Algorithm] 프로그래머스 C++ : 베스트앨범

dokylee 2020. 7. 14. 03:01

 

 

 

 

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

 

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

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

programmers.co.kr

매우 고려하기 복잡했던 문제

 

나는 일단 내가 원하는 대로 vector를 만들어서 하나씩 정렬해갔다.

 

주어진 genres, plays를 하나로 합친 vector => v

 

v의 형식은 (플레이횟수, (고유번호, 장르))로 했다.

 

v를 sort로 정렬하게 되면, 플레이 횟수로 v가 정렬된다.

나중에 "장르 내에서 많이 재생된 노래를 먼저 수록합니다." 조건을 만족시킬 수 있게 됐다.

 

그런 다음에 "속한 노래가 많이 재생된 장르를 먼저 수록합니다." 만족시키기 위해, genres vector를 중복 원소가 없도록 제거했다.

 

이제 중복 원소가 제거된 genres를 가지고 v를 돌면서 어떤 장르가 많이 재생됐는지 genres_sum에 (재생수, 장르) 형식으로 저장했다.

 

마지막으로 genres_sum에 저장된 장르 순서대로 v를 돌면서 많이 재생된 장르 내에서 많이 재생된 노래를 answer에 삽입했다.

 

** 여기서 고려해야할점

1. "스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다.

> 두 개씩만 answer에 넣어야 해서 하나씩 answer에 삽입할 때마다 flag를 1씩 증가시켰다. flag가 3이 되면 세 번째 노래이므로 break

 

2. "장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다."을 만족시켜야 한다.

> 그래서 flag == 2일때, 즉 두 번째 노래를 삽입할 때 이전에 삽입했던 노래와 재생 횟수가 같은데 현재 고유번호가 더 낮은 수라면 swap해줬다.

 

Code

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

vector<int> solution(vector<string> genres, vector<int> plays) {
    vector<int> answer;
    
    vector<pair<int, pair<int, string>>> v;
    
    for(int i=0; i<genres.size(); i++) {
        v.push_back(make_pair(plays[i], make_pair(i, genres[i])));
    }
    
    // 내림차순 정렬 - 장르 내에서 많이 재생된 노래를 먼저 수록 위해
    sort(v.begin(), v.end());
    reverse(v.begin(), v.end());
    
    //for(int i=0; i<v.size(); i++) {
    //    cout << "v1 : " << v[i].first << "\n";
    //    cout << "v2 : " << v[i].second.first << "\n";
    //    cout << "v3 : " << v[i].second.second << "\n";
    //}
    
    // genres 원소 중복 제거
    sort(genres.begin(), genres.end());
    genres.erase(unique(genres.begin(), genres.end()), genres.end());
    
    vector<pair<int, string>> genres_sum;

    // 많이 재생한 장르 찾기
    for(string g : genres) {
        int sum = 0;
        for(int i=0; i<v.size(); i++) {
            if(g == v[i].second.second) {
                sum += v[i].first;
            }
        }
        genres_sum.push_back(make_pair(sum, g));
    }
    
    // 내림차순 정렬 - 속한 노래가 많이 재생된 장르를 먼저 수록 위해
    sort(genres_sum.begin(), genres_sum.end());
    reverse(genres_sum.begin(), genres_sum.end());
    
    int flag = 1, before_listen, before_idx;
    
    for(int j=0; j<genres_sum.size(); j++) {
        for(int i=0; i<v.size(); i++) {
            if(flag == 3) break;
            if(flag == 1) {
                before_listen = v[i].first;
                before_idx = v[i].second.first;
            }
            if(genres_sum[j].second == v[i].second.second) {
                // 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록
                if(flag == 2 && before_listen == v[i].first && before_idx > v[i].second.first) {
                    int tmp = answer.back();
                    answer.pop_back();
                    answer.push_back(v[i].second.first);
                    answer.push_back(tmp);
                }
                else {
                    answer.push_back(v[i].second.first);
                }
                flag += 1;
            }
        }
        flag = 1;
    }
    
    //for(int i=0; i<answer.size(); i++) {
        //cout << "answer : " << answer[i] << "\n";
    //}
    
    return answer;
}