본문 바로가기
알고리즘

C++ 이진탐색 응용

by Chars4785 2019. 1. 26.

이진 탐색을 배웠다. 


이진탐색은 이미 정렬되어 있는 수를 찾는데 유용하다. 


즉 자연수는 이미 정렬 되어 있다. !!!!



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ....


어떤 특정 조건에 맞춰서 값을 찾는 것이다. 


만약 특정 N^2 의 값을 찾기 위함이라면 


반복문을 통해서 넣어 봐도 되지만 이진 탐색을 통해서 하면은 O(logN) 까지 줄어 들게 된다. 


public static int squareRootBSearch(int n) {
    int min = 0;
    int max = n;
    int guess;

    while (min <= max) {
        guess = (min + max) / 2;
        if (guess * guess == n)
            return guess;
        else if (guess * guess > n)
            max = guess - 1;
        else
            min = guess + 1;
    }
    return -1;
}


if 

n= 2

1 2 3 4 5 6 7 8 9 10

중간 값을 5 이므로


중간값 ^2  을 해서 만약에 주어진 값보다 크면


25가 된다 그러면 n^2 인 4보다는 크게 되므로 왼쪽에 답이 있을 확률이 있다. 


그래서 right = mid -1 을 넣고 ( 이미 중간 값은 guess * guess == n 에서 비교 했다. ) 


1 2 3 4 5 에서 찾아보고 


이런식으로 


값을 찾는 것이다. 단지 조건만 달라 진것이다. 


원래 이진 탐색은 


1 3 5 7 9 11 13 15 17 


에서 15를 찾기 위해서  조건이 n == mid 가 되는 것 이었다. 


조건만 달라 졌을 뿐이다. 


-----------------------------------------------------------------------------


Programmers 모의고사 2번 


가로등

길이가 l인 도로에 가로등이 여러대 놓여 있습니다. 전체 도로를 밝히기 위해 좌/우 각각 d만큼을 밝히는 전구를 사려고합니다. 이때 d 값이 충분히 크다면 전체 도로를 밝게 비출 수 있지만, d 값이 작다면 일부 도로는 빛이 닿지 않습니다.

img

도로 길이 l과 가로등의 위치 v가 주어졌을 때, 도로를 모두 밝히는 d 값 중 최솟값을 구해주세요.

시간 복잡도를 고려해 최적값을 찾아낼 수 있는지 물어보는 문제입니다. 시간 복잡도를 고려하지 않고 나이브하게 풀었다면 효율성 테스트케이스를 맞추지 못했을겁니다.

권장 Timecomplexity: O( nlogn )

▼ 정답 예시(소팅 & 그리디) - O( nlogn )

def solution(l, v):
    v.sort()
    ans = max(v[0], l - v[-1])
    for i in range(1, len(v)):
        ans = max(ans, (v[i] - v[i-1] + 1)//2)
    return ans

▼ 정답 예시(이분탐색) - O( nlogn )

def solution(l, v):    
    n = len(v)
    answer = l
    v.sort()

    left, right = 0, l
    while(left <= right) :
        mid = (left + right) // 2

        # 맨 앞 가로등과 맨 뒤 가로등이 도로의 양 끝을 밝히는지 확인
        if v[0] - mid > 0 or v[n-1] + mid < l :
            left = mid + 1
            continue

        # 나머지 가로등으로 이분 탐색
        flag = False
        for i in range(1, n) :
            if v[i-1] + mid < v[i] - mid :
                flag = True
                break
        if flag :
            left = mid + 1
        else :
            answer = mid 
            right = mid - 1
    return answer



출처: https://programmers.co.kr/competitions/92/%EA%B3%B5%EC%B1%84-%EB%8C%80%EB%B9%84-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%A4%EC%A0%84-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-2%ED%9A%8C




'알고리즘' 카테고리의 다른 글

C++ 큰 수 더하기,빼기, 곱하기  (0) 2019.02.08
C++ 소수 ( 쉽게 구하는 방법 )  (0) 2019.02.05
C++ 백준 10157 자리 배정  (0) 2019.01.25
C++ 야구 게임 ( 백준 2503)  (0) 2019.01.23
C++ Binary Search  (0) 2019.01.22

댓글