이 문제는 해시(Dictionary)와 정렬(lambda) 을 함께 사용하는 대표 문제다. 그리고 내가 자주하는 실수를 모아놨다.
- 장르별 총 재생 수를 구하고
- 장르별 노래 목록을 따로 저장한 뒤
- 장르는 총 재생 수 기준으로 정렬하고
- 각 장르 안에서는 노래를 재생 수 기준으로 정렬해야 한다.
즉, Dictionary로 그룹화하고, lambda로 정렬 기준을 설계하는 문제다.
문제를 보고 떠올려야 하는 패턴
장르별로 묶어야 한다
↓
Dictionary / defaultdict
장르별 총합이 필요하다
↓
defaultdict(int)
장르 안의 노래 목록이 필요하다
↓
defaultdict(list)
정렬 기준이 여러 개다
↓
sorted() + lambda
필요한 자료구조
1. 장르별 총 재생 수
stream_genre = defaultdict(int)
예시:
{
"classic": 1450,
"pop": 3100
}
이 자료구조는 장르 순서를 정하기 위해 필요하다.
2. 장르별 노래 목록
stream_song = defaultdict(list)
예시:
{
"classic": [(0, 500), (2, 150), (3, 800)],
"pop": [(1, 600), (4, 2500)]
}
여기서 중요한 점은 노래의 재생 수만 저장하면 안 된다는 것이다.
정답에는 노래의 고유 번호가 들어가야 하므로 반드시
(idx, plays[idx])
형태로 저장해야 한다.
전체 코드
from collections import defaultdict
def solution(genres, plays):
stream_genre = defaultdict(int)
stream_song = defaultdict(list)
answer = []
for idx, genre in enumerate(genres):
stream_genre[genre] += plays[idx]
stream_song[genre].append((idx, plays[idx]))
sorted_stream_genre = sorted(
stream_genre.items(),
key=lambda x: x[1],
reverse=True
)
for genre, total_play in sorted_stream_genre:
songs = sorted(
stream_song[genre],
key=lambda x: (-x[1], x[0])
)
for idx, play in songs[:2]:
answer.append(idx)
return answer
핵심 코드 1: 장르별 총합 구하기
stream_genre[genre] += plays[idx]
이 코드는 장르별 총 재생 수를 누적한다.
classic → 500 + 150 + 800 = 1450
pop → 600 + 2500 = 3100
장르를 정렬할 때 이 값이 기준이 된다.
핵심 코드 2: 장르별 노래 목록 저장
stream_song[genre].append((idx, plays[idx]))
이 코드는 장르별로 노래를 묶는다.
여기서 (idx, plays[idx])로 저장하는 이유는 두 가지다.
idx → 정답에 넣어야 하는 고유 번호
plays[idx] → 정렬 기준이 되는 재생 수
핵심 코드 3: 장르 정렬
sorted_stream_genre = sorted(
stream_genre.items(),
key=lambda x: x[1],
reverse=True
)
stream_genre.items()는 이런 형태다.
[("classic", 1450), ("pop", 3100)]
여기서 x는 하나의 튜플이다.
x = ("classic", 1450)
x[0] = "classic"
x[1] = 1450
따라서
key=lambda x: x[1]
은 총 재생 수 기준으로 정렬하겠다는 의미다.
reverse=True를 사용했기 때문에 총 재생 수가 큰 장르부터 정렬된다.
핵심 코드 4: 장르 안에서 노래 정렬
songs = sorted(
stream_song[genre],
key=lambda x: (-x[1], x[0])
)
stream_song[genre]는 이런 형태다.
[(0, 500), (2, 150), (3, 800)]
여기서 x는 하나의 노래 정보다.
x = (0, 500)
x[0] = 고유 번호
x[1] = 재생 수
정렬 조건은 다음과 같다.
1순위: 재생 수가 높은 순
2순위: 재생 수가 같으면 고유 번호가 낮은 순
그래서 정렬 기준은 이렇게 쓴다.
key=lambda x: (-x[1], x[0])
의미는 다음과 같다.
-x[1] → 재생 수 내림차순
x[0] → 고유 번호 오름차순
이 부분이 이 문제에서 가장 중요한 lambda 활용이다.
핵심 코드 5: 상위 2개만 answer에 넣기
for idx, play in songs[:2]:
answer.append(idx)
각 장르마다 최대 2곡까지만 수록한다.
songs[:2]는 정렬된 노래 중 앞의 두 개만 가져온다.
정답에는 재생 수가 아니라 고유 번호를 넣어야 하므로
answer.append(idx)
를 사용한다.
이 문제에서 자주 하는 실수
1. 재생 수만 저장하는 실수
stream_song[genre].append(plays[idx])
이렇게 하면 나중에 정답에 넣을 고유 번호를 알 수 없다.
반드시 이렇게 저장한다.
stream_song[genre].append((idx, plays[idx]))
2. lambda 오타
lamba
Ture
가 아니라
lambda
True
다.
3. 변수명 덮어쓰기
for idx, stream_genre in enumerate(genres):
처럼 쓰면 기존 딕셔너리 stream_genre를 덮어쓰게 된다.
반복문 변수는 의미에 맞게 작성한다.
for idx, genre in enumerate(genres):
4. 정렬된 변수명 불일치
sorted_stream_genre = ...
로 만들었으면 아래에서도 같은 이름을 써야 한다.
for genre, total_play in sorted_stream_genre:
정렬 패턴 복습
# value 기준 내림차순
sorted(dic.items(), key=lambda x: x[1], reverse=True)
# 튜플에서 두 번째 값 내림차순, 첫 번째 값 오름차순
sorted(arr, key=lambda x: (-x[1], x[0]))
'프로그래밍 > 코딩 테스트, 더 이상 미룰 수 없다' 카테고리의 다른 글
| [코딩 테스트, 더 이상 미룰 수 없다] 코테 오답노트(1) (0) | 2026.06.30 |
|---|---|
| [코딩 테스트, 더 이상 미룰 수 없다] 프로그래머스 lv4 저자 카테고리별 매출 집계하기 - GROUP BY는 '묶는 기준'을 만든다. (0) | 2026.06.28 |
| [코딩 테스트, 더 이상 미룰 수 없다] 프로그래머스 Lv1 실패율 - Python의 매력, Dictionary와 정렬의 자유도 (0) | 2026.06.27 |
| [코딩 테스트, 더 이상 미룰 수 없다] 프로그래머스 lv1 키패드 누르기 - B/DFS와 좌표 계산 분리해서 유형좁히기 (0) | 2026.06.27 |
| [코딩 테스트, 더 이상 미룰 수 없다] 프로그래머스lv1.신규 아이디 추천 -Python 문자열 정복하기 (0) | 2026.06.27 |