-
프로그래머스 고득점 kit(유형정리) - 베스트앨범Algorithm/Hash 2023. 1. 25. 14:27728x90
코딩테스트 연습 - 베스트앨범 | 프로그래머스 스쿨 (programmers.co.kr)
문제 설명
스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.
- 속한 노래가 많이 재생된 장르를 먼저 수록합니다.
- 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
- 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요.
제한사항- genres[i]는 고유번호가 i인 노래의 장르입니다.
- plays[i]는 고유번호가 i인 노래가 재생된 횟수입니다.
- genres와 plays의 길이는 같으며, 이는 1 이상 10,000 이하입니다.
- 장르 종류는 100개 미만입니다.
- 장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.
- 모든 장르는 재생된 횟수가 다릅니다.
["classic", "pop", "classic", "classic", "pop"] [500, 600, 150, 800, 2500] [4, 1, 3, 0] 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]번 노래를 그다음에 수록합니다.
- 장르 별로 가장 많이 재생된 노래를 최대 두 개까지 모아 베스트 앨범을 출시하므로 2번 노래는 수록되지 않습니다.
문제는 이러하다. 솔직히 이 문제를 보고 dictionary를 사용하면 된다는 것은 눈치챌 수 있었지만, 딕셔너리 구조를 어떻게 짜야할지와 딕셔너리 구조를 짜고도 딕셔너리 문법이 익숙하지 않은 탓에 index를 어떻게 처리를 해야하는지 계속 헷갈려서 결국 머리가 터질뻔 할 즈음 구글링을 하게 되었다.
※ 코드의 핵심 사항
1. 딕셔너리 구조
1) {장르 : 총 재생횟수}
2) {장르 : [재생횟수, 고유번호]}
두 개의 해시 테이블을 선언하여 딕셔너리 두 개로 코드를 운영하는 것이 핵심
2. 정렬 방식
1) 총 재생횟수 : 내림차순
2) 재생횟수 : 내림차순
3) 고유번호 : 오름차순
3. total 딕셔너리에 장르를 key로, dic 딕셔너리에 장르를 key로 둔다.
4. key가 있으면 total 딕셔너리에 재생횟수를 계속 담아서 총 재생횟수를 만든다. 없으면 total 딕셔너리에 재생횟수를 새로 담아 초기화 시킨다.
5. key가 있으면 dic 딕셔너리에 재생횟수와 고유번호를 함께 append(추가) 한다. 없으면 dic 딕셔너리에 재생횟수와 고유번호를 새로 담아 초기화 시킨다.
6. 두번째까지만 출력해야 하므로 재생횟수 길이만큼 for문을 돌려서 뽑아낸다.
1) 재생횟수 : 내림차순 정렬 x[i][0]칸에 위치
2) 고유번호 : 오름차순 정렬 x[i][1]칸에 위치
def solution(genres, plays): answer = [] total={} #{장르 : 총 재생횟수} dic={} #{장르 : [재생횟수, 고유번호]} for i in range(len(genres)): genre = genres[i] play = plays[i] if genre in total.keys(): total[genre] += play else: total[genre]=play if genre in dic.keys(): dic[genre].append((play,i)) else: dic[genre]=[(play,i)] # 총 재생횟수 : 내림차순 정렬 x[1]칸에 위치 total = sorted(total.items(), key=lambda x: x[1], reverse=True) for key in total: playlist = dic[key[0]] # 재생횟수 : 내림차순 정렬 x[0]칸에 위치 playlist = sorted(playlist, key=lambda x: x[0], reverse=True) for i in range(len(playlist)): if i==2: break answer.append(playlist[i][1]) # 재생횟수 : 내림차순 정렬 x[i][0]칸에 위치 # 고유번호 : 오름차순 정렬 x[i][1]칸에 위치 return answer
이렇게 해결해 볼 수 있었는데, 구글링을 해도 인덱스가 계속 이해가 잘 안되었다. 파이썬은 기존에 했던 자바와는 다르게 딕셔너리 구조 안에서 한 칸에 리스트를 집어 넣어서 묶음 처리가 가능하다는 것이 아직까지 편하게 와닿지 않는 모양이다. 계속 이차원 배열을 생각하게 되어 코테 해결에 더 어색함을 느끼는 듯 하다.
728x90'Algorithm > Hash' 카테고리의 다른 글
프로그래머스 고득점 kit(유형정리) - 위장 (0) 2023.01.24 프로그래머스 고득점 kit(유형정리) - 전화번호 목록 (0) 2023.01.24 프로그래머스 고득점 kit(유형정리) - 완주하지 못한 선수 (0) 2023.01.23 프로그래머스 고득점 kit(유형정리) - 폰켓몬 (0) 2023.01.23 HashMap 예제 #2 (0) 2022.01.10