On the journey of
[프로그래머스] 베스트앨범, 구명보트(해시, 탐욕 알고리즘) 본문
1. 해시 > 베스트앨범 https://school.programmers.co.kr/learn/courses/30/lessons/42579
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
Q. 문제 설명
스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.
- 속한 노래가 많이 재생된 장르를 먼저 수록합니다.
- 장르 내에서 많이 재생된 노래를 먼저 수록합니다.
- 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
노래의 장르를 나타내는 문자열 배열 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]번 노래를 그다음에 수록합니다.
- 장르 별로 가장 많이 재생된 노래를 최대 두 개까지 모아 베스트 앨범을 출시하므로 2번 노래는 수록되지 않습니다.
※ 공지 - 2019년 2월 28일 테스트케이스가 추가되었습니다.
사실 해시함수를 모르면 정말..정말 어떻게 접근해야 할지 감도 안 오는 문제 아니었을까? 내가 그랬다 .... 우선 해시함수라는 개념은 뭘까? 사실 별것 없다. input을 고정된 길이의 '숫자열로 변환'시켜주는 함수이며, hash는 자료구조이다. 보안 쪽에서도 많이 쓰이는 편인데, 이걸 코테 준비하면서 보게 되다니 (?!)
그렇다면 이런 해시를 어떻게 활용해야 할까? 알고리즘적으로 생각해보자.
1) 장르별로 재생횟수 많은 순서대로 구하기 -> 그 장르에서 재생횟수 많은 노래 2개 고르기
2) 장르별 총 재생횟수 저장하는 해시테이블(list 형태로) 생성 -재생횟수, 고유번호 해시테이블 새로 만들어 정렬
3) Return하는 함수 정의
from collections import deque #double ended queue : 큐의 앞, 뒤에서 삽입, 삭제가 가능한 큐
def solution(genres, plays):
answer = []
total={} #장르별 총 재생횟수
gen_dic={} #장르별 [재생횟수&고유번호]
for i in range(len(genres)):
genre = genres[i]
play = plays[i]
if genres[i] in total.keys():
total[genres[i]]+=plays[i]
gen_dic[genres[i]].append((plays[i],i))
else:
total[genres[i]]=plays[i]
gen_dic[genre]=[(play,i)]
total = sorted(total.items(), key=lambda x: x[1], reverse=True) #정렬
for key in total:
playlist = gen_dic[key[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])
return answer
정말 어렵...다
2. 구명보트 https://school.programmers.co.kr/learn/courses/30/lessons/42885?language=python3
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
Q . 문제 설명
무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다.
예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없습니다.
구명보트를 최대한 적게 사용하여 모든 사람을 구출하려고 합니다.
사람들의 몸무게를 담은 배열 people과 구명보트의 무게 제한 limit가 매개변수로 주어질 때, 모든 사람을 구출하기 위해 필요한 구명보트 개수의 최솟값을 return 하도록 solution 함수를 작성해주세요.
제한사항- 무인도에 갇힌 사람은 1명 이상 50,000명 이하입니다.
- 각 사람의 몸무게는 40kg 이상 240kg 이하입니다.
- 구명보트의 무게 제한은 40kg 이상 240kg 이하입니다.
- 구명보트의 무게 제한은 항상 사람들의 몸무게 중 최댓값보다 크게 주어지므로 사람들을 구출할 수 없는 경우는 없습니다.
![](https://blog.kakaocdn.net/dn/CViV0/btssgJp6Z6r/dITfzTtguXJHvHeoDfeiv0/img.png)
들어가기에 앞서, 카테고리가 Greedy 알고리즘(탐욕법)으로 되어 있다. 이게 무슨 방법이냐면 '최적'인 해답을 찾을 때, 여러 경우 중 하나를 결정해야 할 때마다 그 순간에 최적이라고 생각되는 것을 선택해 나가는 방법이다. 이 문제에 적용해보자. 그러면
1) people list 정렬해서, 제일 무거운 사람과 제일 가벼운 사람을 같이 움직여보자.
2) 합이 보트보다 가벼우면 둘 다 구조
3) 만약 아니라면(보트보다 무거우면) 제일 무거운 사람을 제외
from collections import deque #double ended queue : 큐의 앞, 뒤에서 삽입, 삭제가 가능한 큐
#point - 제일 가벼운 사람, 무거운 사람을 묶어서 처리해야 한다
#answer 변수에 보트 이용 횟수를 추가하자.
def solution(people, limit):
answer = 0
people = deque(sorted(people, reverse = True))
while len(people) > 1:
if people[0] + people[-1] <= limit: # 최댓값과 최솟값 묶기
answer += 1
people.pop() #최소 빼내고
people.popleft() #최대 빼내고
else:
answer += 1
people.popleft()
if people: #people에 1명 남아있는 경우 처리
answer += 1
return answer
결과는?
'코딩테스트 > Python' 카테고리의 다른 글
[프로그래머스] (Python-Greedy) 체육복, 큰 수 만들기 (0) | 2023.09.15 |
---|---|
[알고리즘] Greedy Algorithm[그리디; 탐욕법] (0) | 2023.09.15 |
[프로그래머스] 파이썬 최댓값과 최솟값, JadenCase 문자열 만들기 (1) | 2023.08.12 |
[프로그래머스 Python 2,3] 자연수 뒤집어 배열로 만들기, 정수 제곱근 판별 (0) | 2023.05.02 |
[Python] 프로그래머스 2문제 풀어보기(문자열 나누기, 옹알이2) (0) | 2023.04.27 |