[Algorithm] Programmers : 베스트앨범 by Python

엄희관·2020년 12월 21일
0

Algorithm

목록 보기
36/128
post-thumbnail

[문제 바로가기] https://programmers.co.kr/learn/courses/30/lessons/42579

📌문제 설명

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

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

제한사항

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

입출력 예

입출력 예 설명
classic 장르는 1,450회 재생되었으며, classic 노래는 다음과 같습니다.

  • 고유 번호 3: 800회 재생
  • 고유 번호 0: 500회 재생
  • 고유 번호 2: 150회 재생

pop 장르는 3,100회 재생되었으며, pop 노래는 다음과 같습니다.

  • 고유 번호 4: 2,500회 재생
  • 고유 번호 1: 600회 재생

따라서 pop 장르의 [4, 1]번 노래를 먼저, classic 장르의 [3, 0]번 노래를 그다음에 수록합니다.

💡 문제 풀이

문제에서 제시한 3가지 기준을 만족하는 노래의 고유 번호들을 순서대로 리스트에 담아 출력하면 된다.

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

문제에서도 해시라는 자료구조를 힌트로 주어 사용하였지만 힌트가 없다하더라도 하나의 장르에 다양한 수록곡들이 들어가기 때문에 해시 자료구조를 사용하는 것이 바람직하다고 생각했다.

파이썬에서 딕셔너리(Dictionary)를 이용해 표현할 수 있다.

step 1)
genres_plays : 자료를 담을 딕셔너리

  • key : 장르
  • values : ['해당 장르 총 재생횟수', [('장르에 속한 수록곡, 인덱스)...']]

genres 길이만큼(plays 길이와 같다) 반복문을 돌리면서
if ) genres_plays의 key에 해당 장르가 없다면?
장르와, 재생횟수, 고유번호, 인덱스를 앞서 정의한 key-value형태로 넣어준다.
※ 고유번호와 인덱스는 쌍이므로 튜플(tuple)형태로 저장하였고 한 장르에 다수의 고유번호가 있으므로 리스트 자료구조를 이용하여 튜플들을 담았다.

else ) genres_plays의 key에 해당 장르가 있다면?
해당 장르의 재생횟수를 더하고 리스트에 (수록곡 고유번호, 인덱스)를 추가한다.

step 2)
먼저 해당 장르의 재생횟수를 기준으로 정렬한다.(내림차순)
다음으로, 정렬된 장르들을 하나씩 빼내어 재생횟수(내림차순), 인덱스(오름차순)으로 정렬한다.

step 3)
step 2)에서 정렬한 하나의 장르의 수록곡들에 접근하여 두 개의 수록곡 고유번호를 순서대로 answer에 담는다.
※ 단, 장르에 속한 곡이 하나라면, 하나의 곡만 담는다.

def solution(genres, plays):
    answer = []
    genres_plays = {}
    for i in range(len(genres)):
        if not genres[i] in genres_plays.keys():
            genres_plays[genres[i]] = [plays[i], [(plays[i], i)]]
        else:
            genres_plays[genres[i]][0] += plays[i]
            genres_plays[genres[i]][1].append((plays[i], i))
    for genre in sorted(genres_plays.values(), key=lambda x: -x[0]):
        one_genre = sorted(genre[1], key=lambda x: (-x[0], x[1]))
        if len(one_genre) == 1:
            answer.append(one_genre[0][1])
        else:
            for idx in range(2):
                answer.append(one_genre[idx][1])
    return answer

이번 문제에서도 다중 정렬을 해야하다보니 lambda를 활용할 수 있었다.

딕셔너리 자료구조의 내장함수 keys(), values(), items() 를 사용하여 원하는 자료에 대한 정렬이 가능하다.

profile
허브

0개의 댓글