https://programmers.co.kr/learn/courses/30/lessons/43236
코딩테스트 연습 - 징검다리 | 프로그래머스
출발지점부터 distance만큼 떨어진 곳에 도착지점이 있습니다. 그리고 그사이에는 바위들이 놓여있습니다. 바위 중 몇 개를 제거하려고 합니다. 예를 들어, 도착지점이 25만큼 떨어져 있고, 바위가 [2, 14, 11, 21, 17] 지점에 놓여있을 때 바위 2개를 제거하면 출발지점, 도착지점, 바위 간의 거리가 아래와 같습니다. 제거한 바위의 위치 각 바위 사이의 거리 거리의 최솟값 [21, 17] [2, 9, 3, 11] 2 [2, 21] [11, 3
programmers.co.kr

이분탐색 문제.
distance 제한사항이 1,000,000,000인 것에서 이분탐색 느낌이 강하게 오긴 했지만,
이분탐색에서 기준으로 삼을 값이 뭔지 도저히 감이 안 와서 다른 블로그 해설을 참고해야만 했다.
이분탐색의 기준은 '돌과 돌 사이의 거리' 였고, 이분탐색을 진행하는 방법은
1. '돌과 돌 사이의 거리가 이분탐색 기준값보다 작을 경우 뒤쪽 돌을 삭제한다'
2. 삭제한 돌의 개수가 기준 n보다 클 경우 돌과 돌 사이의 거리를 줄이고, n보다 작거나 같을 경우 거리를 늘리는 식으로 이분탐색을 진행한다.
'무엇을 이분탐색 값으로 설정할 것인지', '이분탐색의 left, right값을 변화시킬 기준은 무엇인지' 익숙해지는 게 왜 이리 어려운지 모르겠다.
import math | |
def solution(distance, rocks, n): | |
rocks.sort() | |
rocks.append(distance) | |
left, right = 0, distance | |
# 바위 사이의 최소거리보다 거리가 작을 경우 돌 삭제. | |
# 거리가 클 경우, 이 값들 중 최솟값을 구해둔다. | |
answer = 0 | |
while left <= right: | |
# 이전 돌 | |
prev = 0 | |
# 돌 거리 최솟값. | |
mins = math.inf | |
# 제거한 돌 개수 | |
removed_rocks = 0 | |
# 바위 사이의 최소거리 | |
mid = (left + right) // 2 | |
# 각 돌을 돌면서 제거할 돌을 찾는다. | |
for i in range(len(rocks)): | |
if rocks[i] - prev < mid: | |
removed_rocks += 1 | |
else: | |
mins = min(mins, rocks[i] - prev) | |
prev = rocks[i] | |
# 제거한 돌 개수가 기준보다 많다 = 바위 제거를 줄여야 한다. | |
# 바위 사이 최소거리의 기준을 낮춰야 한다 | |
if removed_rocks > n: | |
right = mid - 1 | |
# 제거한 돌 개수가 기준보다 적다 = 더 많은 바위 제거가 필요 | |
# = 바위 사이 최소거리 기준을 높여야 한다 | |
else: | |
answer = mins | |
left = mid + 1 | |
return answer | |
'프로그래밍 > 코딩테스트 문제풀이' 카테고리의 다른 글
[Python] 백준 1654. 랜선 자르기 (0) | 2020.01.09 |
---|---|
[Python] 백준 2231. 분해합 (0) | 2020.01.08 |
[Python] 프로그래머스. 멀리 뛰기 (Level 3) (0) | 2020.01.06 |
[Python] 백준 14891. 톱니바퀴 (1) | 2020.01.05 |
[Python] 백준 17135. 캐슬 디펜스 (0) | 2020.01.04 |