문제 링크 >> 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개 미만입니다.
- 장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.
- 모든 장르는 재생된 횟수가 다릅니다.
👈 출력
💡 사용된 개념
✔️ enumerate
인덱스의 번호와 컬렉션의 원소를 tuple 형태로 반환한다.
>>> t = [1, 5, 7, 33, 39, 52]
>>> for p in enumerate(t):
... print(p)
...
(0, 1)
(1, 5)
(2, 7)
(3, 33)
(4, 39)
(5, 52)
✔️ sort()
항목 간 < 비교만 사용해 리스트를 정렬한다.
sort(*, key=None, reverse=False)
- key : 인자를 하나 받아들이는 함수를 지정, 이때 각 리스트 요소에서 비교 키를 추출하는 데 사용됨.
- reverse : 논리값. True로 설정 시 > 비교를 한 것과 같음.
✔️ 파이썬 튜플 리스트 정렬
기본적으로 첫 번째 원소를 기준으로 정렬되지만 기준이 되는 원소를 특정하고자 할 때 다음의 방법을 이용할 수 있다.
# 첫 번째 원소를 기준으로 정렬
# 오름차순
tuple_list.sort(key=lambda x: x[0])
# 내림차순
tuple_list.sort(key=lambda x: x[0], reverse=True)
tuple_list.sort(key=lambda x: -x[0])
# 튜플의 두 번째 원소를 기준으로 정렬 후 같은 값이 나오면 첫 번째 원소 정렬
tuple_list.sort(key=lambda x: (x[1],x[0]))
📝 풀이
def solution(genres, plays):
answer = []
d = {}
sum_d = {}
for genre, play in zip(genres, enumerate(plays)):
temp = []
if genre in d:
sum_d[genre] += play[1]
d[genre].append(play)
else:
sum_d[genre] = play[1]
temp.append(play)
d[genre] = temp
sum_d = sorted(sum_d.items(), key=lambda x:x[1], reverse=True)
for k in sum_d:
song = d[k[0]]
song.sort(key=lambda x: x[1], reverse=True)
for i in range(len(song)):
if i == 2:
break
answer.append(song[i][0])
return answer
차근차근 원하는 형식의 데이터를 뽑아나가는 형식의 문제였다.
문제를 풀기 위해 필요한 건 두 가지였다.
- 장르 별 노래의 재생횟수 총 합
- 장르 별로 구분된 노래의 재생 횟수들과 해당 인덱스 번호
1을 sum_d에 저장하기로 했고 2를 d에 저장하기로 했다.
각 항목을 저장하기 위해 이전 문제를 풀 때 썼던 zip()과 enumerate()를 결합해 사용했다.
sum_d에는 단순하게 해당 장르의 재생 횟수를 더해주었다.
d의 경우에는 장르마다 (인덱스 번호, 재생 횟수)의 튜플을 담아야 하기 때문에 temp라는 빈 배열을 임시로 선언하고 장르가 처음 등장했을 때 temp에 처음 등장한 튜플을 담아 배열의 형태로 value에 저장했다.
이후 같은 장르가 등장할 때마다 해당 배열에 값을 추가한다.
for문이 끝난 후 노래를 고르는 첫 번째 조건에 따라 속한 노래가 많이 재생된 장르를 찾기 위해 sum_d를 value값을 기준으로 내림차순 정렬해 주었다.
정렬이 끝나면 sum_d는 제일 많이 재생된 장르가 맨 앞에 위치한 (장르, 재생 횟수)의 튜플들을 가진다.
sum_d를 이용해 for문을 돌며 key값을 sum_d의 장르로 하는 d의 value를 song에 저장한다.
그러면 song에는 해당 장르의 (인덱스번호, 재생 횟수) 튜플들이 리스트의 형태로 들어있다.
노래를 고르는 두 번째 조건에 따라 장르 내에서 많이 재생된 노래를 찾기 위해 튜플의 두 번째 원소인 재생 횟수를 기준으로 song을 내림차순 정렬한다.
각 장르 별로 최대 2개의 노래만을 고르므로 song에서 2개의 원소(인덱스 번호)를 골라 answer에 넣어준다.
🔍 참조
enumerate https://wikidocs.net/16045
sort https://docs.python.org/ko/3/library/stdtypes.html#list.sort
파이썬 튜플 리스트 정렬 https://hansuho113.tistory.com/28
'Algorithm > Python' 카테고리의 다른 글
[LeetCode] Group Anagrams (0) | 2022.01.25 |
---|---|
[LeetCode] Two Sum (0) | 2022.01.25 |
[프로그래머스] 위장 (0) | 2022.01.24 |
[프로그래머스] 전화번호 목록 (0) | 2022.01.24 |
[프로그래머스] 완주하지 못한 선수 (0) | 2022.01.24 |
댓글