너무 오랜만에 풀어봐서 진짜로 다 까먹은 듯한 binary search ㅠㅠ 문제를 들여다보다가 이게 왜 BS 지…? 싶었다
아마도 내가 제대로 이해를 못해서 그런걸까,,, 엉엉
- 입국심사
처음에 작성한 코드는 아래와 같은데, test case는 통과했지만 답은 틀렸당
def solution(n, times):
'''
input : 입국심사를 기다리는 사람 수 n,
각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times
'''
answer = 0
times.sort()
# 한번에 심사를 받을 수 있는 경우
if n<=len(times): answer = times[n-1]
# 한번에 심사를 받을 수 없는 경우
else:
if n%len(times) == 0:
min_test = 10000
for i in range(1,len(times)+1):
#print(i)
if min_test > solution(n-i, times)+times[i-1]:
min_test = solution(n-i, times)+times[i-1]
print(min_test)
answer = min_test
#print(answer)
else:
#print(times[n%len(times)-1])
#print((int(n/len(times))+1))
answer = times[n%len(times)-1]*(int(n/len(times))+1)
return answer
이런저런 코드를 작성해봤는데도 여전히 너무 틀렸고,
한시간이 넘게 고민해도 해답을 찾을 수 없어서, 내가 binary search의 기준 및 어떤 값을 탐색해야 할지를 모르는 것 같아, 다른 분들의 풀이을 참고하였다.
아 앞으로 다른 분들의 풀이를 참고할 때에는 그냥 오 그렇군!
하고 넘기지 않고, 최소 3명의 코드를 비교해보고 스스로 짜봐야 겠다.. 안그러면 빠르게 까먹는듯 ㅠㅠ
위 참고 1, 2, 3에서는 공통적으로 아래와 같이 설정했다
-
BS 의 기준: 주어진 시간동안 각 심사원이 심사를 했을 때, 심사를 마친 사람이 N명 이상인지 (이상이면 시간을 줄이고, 이하면 시간을 늘린다 )
-
BS 할 값: 한명의 심사원에게 얼마의 시간을 줄 것인가
def solution(n, times):
'''
input : 입국심사를 기다리는 사람 수 n,
각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times
'''
answer = 0
left, right = 1, max(times)*n # 오래 걸리는 심사관에게 전부 받는 경우가 worst case
while left<=right:
# 한 심사관에게 주어진 경우
mid = ((left+right)//2)
people = 0 # 각 심사관이 제한 시간동안 심사할 수 있는 사람의 총 수
for t in times: # 각 심사위원이
people += mid//t # 주어진 시간동안 심사할 수 있는 사람의 수
if people>=n: break # 전부 심사한 경우 종료
if people >= n: # n명을 심사할 수 있는 경우, 시간을 줄여볾
right = mid-1
answer = mid
else: # 시간안에 심사가 불가능한 경우, 시간을 늘림
left = mid+1
return answer
- 징검다리
이번에는, 제일 먼저 binary search의 기준 및 수행할 값을 먼저 고민해보기로 했다!
(여전히 완전탐색으로만 접근하려는게 너무 힘들다 ㅠㅠ )
우선 처음으로 했던 접근은 최악의 시나리오였다! 바위 개수 == 제거해야할 개수라서, 간격의 최소값이 distance인 경우가 최악의 시나리오 이므로,
우리가 binary search해야 하는 값은 각 돌들 사이의 거리
이다.
이를 위해서는 돌을 몇개를 어떻게 뺴야하는지가 관건인 셈인데,
이를 binary search의 기준으로 표현해보면, 뺀 돌의 개수를 n과 비교하는 것
이다.
그런데 대강 이해는 했는데, 이걸 구체적으로 어떻게 binary search에 나타낼지는 너무 모르겠더라고 ㅠㅠㅠ
최대와 최소의 값을 어떻게 설정하는지는 이해했는데, mid값이 무엇을 의미하는지
와 어떻게 돌을 제거할 것인지
를 코드에 구현하는 과정에서 막혔다 ㅠㅠ
이번에도 조금씩 다른 분들의 코드를 참고했다.
[참고 2](https://coreenee.github.io/2020/05/13/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4(%EC%A7%95%EA%B2%80%EB%8B%A4%EB%A6%AC)
mid가 바위 사이의 최소 거리인 이유
는, 바위 사이의 최소 거리보다 각 돌들 사이의 거리가 가까우면 해당 돌을 제거하기 위해서 임을 알게 되었당…
def solution(distance, rocks, n):
'''
input: 출발지점부터 도착지점까지의 거리 distance,
바위들이 있는 위치를 담은 배열 rocks, 제거할 바위의 수 n
output: 바위를 n개 제거한 뒤 각 지점 사이의 거리의 최솟값 중에 가장 큰 값
binary search의 기준: 뺀 돌의 개수를 n과 비교
binary search할 값: 각 돌 사이의 거리
'''
answer = 0
# 최악의 시나리오: 바위 개수 == 제거해야할 개수라서, 간격의 최소값이 distance인 경우
# 즉, binary search할 값은 간격
# binary search의 기준은 제거한 돌의 개수를 n과 비교하는 것이다 (n보다 적으면 간격을 좁히고, n보다 많으면 간격을 넓힘)
left, right = 0, distance
rocks.sort() # 바위의 위치를 우선 정렬
#rocks.append(distance)
while left<=right:
mid = (left+right)//2
removed_rocks = 0
# 거리 측정을 위해, 이전단계의 돌의 값 변수 지정
prev = 0
min_dist = 10000001
for rock in rocks:
if (rock-prev)<mid: removed_rocks+=1
else:
min_dist = min(min_dist, rock-prev)
prev = rock
if removed_rocks > n: # 만약 제거를 더 많이 해야한다면,
right = mid-1 # 돌 사이의 간격을 좁힌다
else:
left = mid +1 # 돌 사이의 간격을 넓힌다
answer = min_dist
return answer
나름 난이도 쉬움
이라서 먼저 공략해본 건데, binary search가 이렇게 어려웠나? 싶었음,,,
중요한 것은,
-
binary search의 기준, binary search를 수행할 값을 찾아보자 !!
-
해당 범위에 맞게 left, right를 지정하고, ` mid의 의미` 를 확인해보자
-
기준에 대해, 어떤 결과가 나왔을 때 ` mid = left+1
이 되거나
mid = right-1` 이 되는지 고민하자
-
-
for 문 중심의 사고를 바꾸자 ㅠㅠ