카테고리 없음

99클럽 코테 스터디 2일차 TIL - [이분탐색]

레야_Reya 2024. 10. 29. 18:01
오늘의 문제

 

백준 11561번 (https://www.acmicpc.net/problem/11561)


정답 코드
T = int(input())

case = []

for _ in range(T):
    case.append(int(input()))

for N in case:
    l = 1
    r = N
    result = 0

    while l <= r:
        mid = (l + r) // 2
        dist_sum = mid * (mid + 1) // 2  # mid개의 징검다리를 밟았을 때의 누적 거리

        if dist_sum <= N:
            l = mid + 1
            result = mid  # 현재 mid 값이 가능한 징검다리 개수일 수 있음. 값 갱신.
        else:
            r = mid - 1

    print(result)

오늘의 회고 & 문제 해설

 

어제에 이어서 다시 등장한 이분탐색 문제였다.

어제 한 번 원리를 파악한 덕에 조금은 빠르게 문제 파악을 할 수 있었다.

오늘 내가 짠 코드는 파이썬이라서 가능한 코드이다. 자바라면 r = 10**16 으로 초기부터 설정해주어야 한다고 한다.

파이썬이라 다행이다... 만세! 🙌 🙌

 

Start point = 0, End point = N (input으로 주어지는 총 다리의 수) 으로 잡는다.

이 때, N의 최대 범위가 10^16 이기 때문에, 이진탐색 없이는 시간초과가 뜰 수밖에 없다.

 

이진탐색을 했을 때 계산의 시간복잡도를 어마어마하게 낮출 수 있는데, 어느 정도냐면...

10^3 = 1000 이고, 2^10 = 1024 이므로, 대략 이 둘을 비슷한 크기라고 생각을 해보자.

그러면 10^9 = 10억 이고, 이 숫자가 대략 2^30 과 비슷하다고 생각했을 때, 이진탐색을 하는 경우 log2(2)^30 수준으로 낮아진다.

다시 말해서, 그냥 하면 10억번 계산할 식을 이진탐색을 수행하면 30번 만에 끝낸다는 말이다...!

마찬가지로, 10^12 = 1조 라서 대략 2^40 이므로, 이진탐색으로 계산을 하면 40번만에 계산이 끝날 수 있다.

이진탐색의 위대함이 확 체감이 되는 숫자이다...! 😲👏👏👏


이진 탐색 반복문 (while l <= r)

  • mid 값을 l과 r의 중간 지점으로 설정한다.
  • dist_sum = mid * (mid + 1) // 2를 계산한다. 이는 1부터 mid까지 징검다리를 밟았을 때의 누적 거리와 같다.

조건문

  • dist_sum <= N인 경우! N 이하이므로 현재 mid 값이 가능함을 의미한다.
    • l = mid + 1로 설정하여 더 큰 mid 값을 탐색해본다.
    • result를 mid로 갱신하여 최대 mid 값을 저장한다.
  • dist_sum > N인 경우! 거리가 초과했으므로 r = mid - 1로 설정하여 더 작은 mid 값을 찾아본다.

결과 출력

  • 각 테스트 케이스마다 최종 result 값을 출력하여, N을 넘지 않는 최대 징검다리 개수를 출력한다.