문제설명
본 문제는 난이도와 해결 시간이 주어진 퍼즐들을
제한 시간내에 해결할 수 있는 최소 숙련도 (level)을 구하는 문제이다.
여기 level이란, 퍼즐의 난이도와 같은 의미로 보면 된다.
본 문제의 입력은 총 3가지이다.
문제의 난이도를 갖고 있는 배열 diffs
각 문제를 해결하는 데에 걸리는 시간들의 배열 times
문제 해결을 위한 제한시간 limit
각 변수들 사이의 상관관계는 문제를 해결하는 시간에 있다.
문제를 해결하는 시간을 구하는 방법은 아래와 같다.
level 보다 난이도가 높은 문제에 대해선, diff - level 만큼 실수하게 된다.
이 때, 각 실수는 (이전 퍼즐의 시간 + 현재 퍼즐의 해결 시간) 만큼의 시간이 추가 소요되며
실수 후에 퍼즐을 해결하기 위한 time이 추가 소요된다.
또한 level 보다 낮거나 같은 난이도의 모든 문제는 time만큼의 시간을 소요하여 퍼즐을 해결할 수 있다.
이렇게 경우의 수를 살펴서 최소 숙련도를 구하면 된다.
제한사항
제한 사항을 보면 문제의 개수는 30만개이다.
간단히 어림짐작해도 시간이 조금 부족할 수도 있음을 고려한 알고리즘을 활용해야 될 것으로 보인다.
문제풀이
앞서 문제를 이해하는 과정에서 알 수 있듯, 본 문제는 최적의 level을 구하는 문제이다.
그 과정에서 알 수 있는 점은 숙련도가 낮을 경우 퍼즐을 여러번 틀리게 되며, 이 때 시간이 더욱 소모되고
숙련도가 높을 경우 점점 적은 시간을 사용하게 된다.
(즉, 총 걸리는 시간과 숙련도는 반비례 관계에 있다.)
하지만, 모든 숙련도에서 나올 수 있는 경우의 수를 탐색하기엔,
시간이 터무니 없이 부족하다. (입력 배열 크기가 30만개)
이 정도 내용을 읽으면 어느정도 머리에 그려졌을 텐데,
해당 문제는 이진탐색 알고리즘으로 쉽게 해결할 수 있다.
추가적으로 본인은 14번 테스트 케이스에서 여러번 시행착오를 겪었는데,
해당 예외 케이스 같은 경우, diff가 [1, 2]와 같이 주어지는 경우,
반드시 0으로 반환하는 문제였다.
이는 문제의 설명을 제대로 읽지 않아서 발생한 문제이다.
모든 값은 양수이다.
이를 이해하면 문제를 쉽게 해결해볼 수 있다.
정답코드
def solution(diffs, times, limit):
# 퍼즐의 난이도와 소요 시간을 묶어줌
puzzles = list(zip(diffs, times))
start, end = 0, max(diffs) # 이진 탐색 범위 (숙련도는 난이도 중 가장 큰 값까지 가능)
last_cur = 0 # 마지막 숙련도 저장
# 이진 탐색 시작
while start <= end:
total_times = 0
cur = (start + end) // 2 # 중간 숙련도
# 현재 숙련도로 각 퍼즐을 풀 때의 시간을 계산
for i, (diff, time) in enumerate(puzzles):
if cur < diff: # 숙련도가 부족하여 틀릴 때
if i > 0:
total_times += (times[i-1] + time) * (diff - cur)
else:
total_times += time * (diff - cur)
total_times += time # 기본적으로 소요 시간 추가
# 계산된 시간과 제한 시간을 비교
if total_times <= limit: # 제한 시간 내에 해결 가능하면 숙련도 낮춰보기
last_cur = cur # 최적 숙련도 갱신
end = cur - 1
else: # 제한 시간을 넘기면 숙련도 높이기
start = cur + 1
if last_cur == 0:
return 1
return last_cur # 최소 숙련도 반환
'CodingTest > programmers' 카테고리의 다른 글
[프로그래머스] 인사고과 Python 파이썬 (0) | 2024.10.02 |
---|---|
[프로그래머스] 네트워크 (Python) (0) | 2024.09.30 |
[프로그래머스] 게임 맵 최단거리 (Python) (0) | 2024.09.28 |
[프로그래머스] 뒤에있는 큰 수 찾기 (Python) (0) | 2024.09.24 |
프로그래머스 PCCP 기출문제 1번 - 동영상 재생기 (1) | 2024.09.18 |