코딩테스트 연습 - 무지의 먹방 라이브 | 프로그래머스 (programmers.co.kr)
효율성 테스트에 부분 점수가 있는 문제입니다.
평소 식욕이 왕성한 무지는 자신의 재능을 뽐내고 싶어 졌고 고민 끝에 카카오 TV 라이브로 방송을 하기로 마음먹었다.
그냥 먹방을 하면 다른 방송과 차별성이 없기 때문에 무지는 아래와 같이 독특한 방식을 생각해냈다.
회전판에 먹어야 할 N 개의 음식이 있다.각 음식에는 1부터 N 까지 번호가 붙어있으며, 각 음식을 섭취하는데 일정 시간이 소요된다.무지는 다음과 같은 방법으로 음식을 섭취한다.
무지가 먹방을 시작한 지 K 초 후에 네트워크 장애로 인해 방송이 잠시 중단되었다.무지는 네트워크 정상화 후 다시 방송을 이어갈 때, 몇 번 음식부터 섭취해야 하는지를 알고자 한다.각 음식을 모두 먹는데 필요한 시간이 담겨있는 배열 food_times, 네트워크 장애가 발생한 시간 K 초가 매개변수로 주어질 때 몇 번 음식부터 다시 섭취하면 되는지 return 하도록 solution 함수를 완성하라.
1
을 반환하면 된다.1
이상 2,000
이하이다.1
이상 1,000
이하의 자연수이다.1
이상 2,000,000
이하의 자연수이다.1
이상 200,000
이하이다.1
이상 100,000,000
이하의 자연수이다.1
이상 2 x 10^13
이하의 자연수이다.입출력 예 #1
# 프로그래머스 '무지의 먹방라이브'
# 힙 구조 라이브러리
import heapq
def solution(food_times, k):
# answer를 못 구할 경우 -1
answer = -1
# 힙 리스트
hq = []
# 힙리스트에 (섭취 시간, 순번)을 넣어준다.
for i in range(len(food_times)):
heapq.heappush(hq, (food_times[i], i+1))
length = len(hq) # 음식 갯수 (한 사이클)
pre = 0 # 전 음식의 섭취 시간
while hq: # 리스트가 빌때까지
# 가장 적은 섭취시간과 전 음식시간의 섭취시간을 빼주고, 음식 갯수를 곱해준다.
diff = (hq[0][0] - pre) * length
# 한사이클의 음식량을 빼줄 diff가 k보다 작거나 같으면 빼준다.
if diff <= k:
k -= diff
# 한사이클을 돌렸기 때문에 해당 음식은 다먹었으니 제외 시킨다.
length -= 1
# 음식을 리스트에서 제외시키고, 해당 순서의 섭취시간을 변수에 업데이트 해준다.
pre, _ = heapq.heappop(hq)
# 한 사이클을 돌리지 못할때
else:
# 한사이클을 돌리지 못하기 때문에 k와 남은 음식의 개수를 나눈 나머지가 해당 인덱스가 된다.
idx = k % length
# 현재 리스트가 섭취시간으로 정렬되어 있어서 두번째 값인 순번으로 정렬해준다.
hq.sort(key = lambda x: x[1])
# 답을 찾아주고 멈춰준다
answer = hq[idx][1]
break
return answer
예시의 [3 ,1 ,2] 의 경우의 그림
그림 출처 : https://youtu.be/zpz8SMzwiHM
처음 이 문제를 풀때 왼쪽 그래프처럼 진행되게 풀었고, 결국 완전 탐색으로 연산을 하기 때문에 시간에서도 오류가 났다.
변명을 하자면 입출력 예 설명을 보면서 구상을해서 그런가..
그래서 힙으로 풀어야겠다는 생각은 들었지만 막상 접근하기 어려웠다.
이 후 좋은 설명을 해주셨던 강의를 보고 풀 수 있었다.(해당 그림 아래 링크)
효율적으로 풀려면 오른쪽 그림처럼 되야하는데 해당 그림처럼 정렬을 진행할때 (섭취시간, 순번)
의 튜플 구조로 넣어서 남은 k보다 한 사이클이 클때 다시 순번을 기준으로해서 정렬해서 정답 인덱스를 찾아준다.
설명하기 너무 어렵지만.. diff가 섭취시간*음식의 개수(해당 그림의 세로*가로)
인데 이것이 앞에서 언급했던 한 사이클을 뜻하는데 섭취시간 순으로 정렬되어 있기 때문에 한번에 많은 수를 줄여 줄 수 있었다.