본문 바로가기

알고리즘 문제 풀이/Baekjoon

2110 - 공유기 설치

반응형
SMALL

https://www.acmicpc.net/problem/2110

 

2110번: 공유기 설치

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (1 ≤ xi ≤ 1,000,000,000)가 한 줄에 하나씩 주어진다.

www.acmicpc.net

Binary Search 문제입니다.

최근 면접 준비로 기본적인 알고리즘을 공부하고 있는데, 딱 좋은 알고리즘이 Binary Search 같네요.

마침 제가 Binary Search 문제였다는 것을 알았기에 풀 수 있었던 문제였지만, 그게 아니었다면 Binary Search까지 생각해내기 어려웠을 거 같습니다.

 

왜 Binary Search를 사용하냐면 결국 저희는 서로 인접한 거리 중 최대 거리를 찾는 것입니다. 즉, 답은 무조건 정해져있습니다. 그렇다면 그 문제를 푸는 것보단, 답이 이미 정해져 있다고 가정하고 문제를 해석해보면 어떨까요?

 

그런 발상으로 Binary Search를 사용했습니다. 답이 될 수 있는 가장 큰 값과 작은 값을 뺀 거리를 N과 1 사이엔 무조건 답이 있으니 그 사이에서 답을 찾아보는거죠. 답을 찾는 시간복잡도는 O(logN)이 되겠죠. (순전한 답을 찾는 복잡도입니다. 추가적인 연산으로 그 답이 맞는가, 틀린가가 필요합니다)

 

답을 구했으면 그 답이 가능한지 파악해보고, 설치된 공유기가 적다면 그 거리를 줄여서 공유기를 더 설치를 해야합니다. 왜냐면 저희는 C만큼 공유기를 설치할 것이라고 정해놓았기 때문이죠.

 

설치된 공유기가 C보다 많으면 어떻게 될까요? 그 정답은 진짜 정답이 될 수 있는 후보에 오르게 됩니다. 이런 식으로 Binary Search를 진행하면서 답을 찾아간다면, 최종 답을 구할 수 있습니다.

 

def binarySearch(L, R):
    global N, C, result, answer
    mid = (L + R) // 2
    if L > R: # 이 부분에서 >= 을 사용했는데, >= 을 해버리면 답이 아닌 답도 정답 후보에 오르게됩니다.
        return mid
    cnt = 1
    cur = 0
    nxt = 1
    while True:
        if nxt >= N:
            break
        if arr[nxt] - arr[cur] < mid:
            nxt += 1
            continue
        else:
            cnt += 1
            cur = nxt
            nxt = cur + 1
    if cnt < C:
        return binarySearch(L, mid - 1)
    else:
        answer = mid
        return binarySearch(mid + 1, R)

N, C = list(map(int,input().split()))

arr = []
for _ in range(N):
    num = int(input())
    arr.append(num)

arr.sort()

first = arr[0]
end = arr[-1]

max_ = end - first
min_ = 1
binarySearch(min_, max_)

print(answer)

 다시 한 번 풀어봤는데 더 깔끔한 코드가 나왔네요. 다시보니 비슷한거 같기도 하고..

def binarySearch(minn, maxx):
    global C 
    mid, cur, nxt, cnt  = (minn + maxx) // 2, 0, 1, 1
    if minn > maxx:
        return mid
    
    ou = 0
    # 공유기 갯수 확인
    while 1:
        if cnt > C:
            ou = 1
            break
        elif nxt >= len(arr):
            break
        elif arr[nxt] - arr[cur] >= mid:
            cnt += 1
            cur = nxt
            nxt += 1
        else:
            nxt += 1

    if cnt < C:
        return binarySearch(minn, mid - 1)
    else:
        return binarySearch(mid + 1, maxx)

N, C = list(map(int,input().split()))

arr = []

for _ in range(N):
    num = int(input())
    arr.append(num)

arr.sort()

minn, maxx = arr[0], arr[-1]

print(binarySearch(1, maxx- minn))
반응형
LIST

'알고리즘 문제 풀이 > Baekjoon' 카테고리의 다른 글

1717 - 집합의 표현  (0) 2019.11.18
1976 - 여행 가자  (0) 2019.11.17
17141 - 게리맨더링  (0) 2019.09.20
11052 - 카드 구매하기  (0) 2019.08.12
5622 - 다이얼  (0) 2019.08.11