[Algorithm] 이분탐색 알고리즘 - Upper Bound/Lower Bound

2024. 12. 8. 21:35·ALGORITHM

안녕하세요.

오늘은 이분 탐색 알고리즘에 대해 알아보겠습니다.

 

또한 탐색의 경계가 되는 Upper Bound와 Lower Bound에 대해 설명하고,

이분탐색의 탐색 범위에 관한 얘기도 해보겠습니다.

 

 

 

 

이분탐색이란?

정렬된 배열에서, 원하는 값을 효율적으로 찾는 알고리즘입니다.

배열의 중간값이 찾고자하는 값보다 크면 오른쪽을, 작으면 왼쪽을 버려 원하는 값을 찾습니다.

동작 과정은 다음과 같습니다.

 

1. left = 0, right = arr.length

2. 왼쪽을 버리면 left = mid+1로, 오른쪽을 버리면 right = mid로 업데이트 합니다.

3. 하한값 탐색 시, mid >= taret일 때만 버립니다.

4. 상한값 탐색 시, mid > target일 때만 버립니다.

5. 배열 탐색은 left < right 일 때까지만 진행합니다.

6. left값을 리턴합니다.

 

 

 

 

Upper Bound(상한선)

찾고자 하는 값을 초과하는 값이 처음 등장하는 위치를 반환합니다.

 

예) 1을 찾고자 할 때 : 1-1-2-3, 0-0-2-3

 

     간단하게 자바로 구현한 코드는 다음과 같습니다.

public static int upperBound(int[] arr, int target) {
    int left = 0;
    int right = arr.length;

    while (left < right) {
        int mid = (left + right) / 2;
        
        // 목표값을 초과할 때만 오른쪽 버리기
        if (arr[mid] > target) {
            right = mid;
        } else { // 같을 때는 왼쪽 버리기
            left = mid + 1;
        }
    }
    return left;
}

 

 

 

 

 

 

 

Lower Bound(하한선)

찾고자 하는 값 이상(= 같은 값 포함)이 처음 등장하는 위치를 반환합니다

 

예) 1을 찾고자 할 때, 1-1-2-3 이라면 첫번째 1을 반환합니다.

 

     3-1-1-2-3과 같은 경우에선 3을 반환하여 오류가 생기는 것이 아닐까 고민했습니다.

     하지만 이분 탐색은 항상 정렬된 배열에 대해서 수행하기 때문에 위와 같은 경우는 고려하지 않아도 됩니다.

 

     간단하게 java로 구현한 코드는 다음과 같습니다.

public static int lowerBound(int[] arr, int target) {
    int left = 0;
    int right = arr.length; // 반닫힌구간

    while (left < right) {
        int mid = (left + right) / 2;
        
        // 목표값 이상일 때 오른쪽 버리기
        if (arr[mid] >= target) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left;
}

 

 

 

 

 

 

이분 탐색의 탐색범위는 반닫힌구간 [left, right)

이분 탐색으로 탐색 시, 반닫힌 구간 [left, right)을 사용해야 합니다.

이에 관한 많은 설명을 읽었으나,, 이해하지 못해 그냥 외우기로 했습니다..

 

자세한 설명을 원한다면 아래 글을 참조하시면 좋을 것 같습니다.

이분탐색은 반닫힌구간을 써야하는 이유

 

 

 

 

 

 

 

이분 탐색을 이용하여 특정값 포함 여부 찾기

// 이분탐색은 항상 반열린 구간으로 탐색하므로, binarySearch(target, 0, n)으로 시작한다.

static boolean binarySearch(int target, int left, int right) {
    while (left < right) { // 구간이 존재하는 동안 반복
        int mid = (left + right) / 2;

        if (arr[mid] == target) return true;

        if (arr[mid] > target) {
            right = mid; // 왼쪽 구간, mid 제외
        } else {
            left = mid + 1; // 오른쪽 구간, mid 제외
        }
    }
    
    return false; // 더 이상 구간이 없으면 false
}

 

 

 

 

정리

이분 탐색은 중간값을 기준으로 잡습니다.

중간값이 목표값보다 작다면 왼쪽을 버리고(left = mid + 1), 중간값이 크다면 오른쪽을 버리며(right = mid) 탐색합니다.

Upper Bound는, 목표값을 초과하는 처음 위치를 반환합니다. (목표 + 1의 인덱스)

Lower Bound는, 목표값 이상인 처음 위치를 반환합니다. (목표의 인덱스)

항상 반닫힌 구간에 대해 수행해야합니다. [left, right)

'ALGORITHM' 카테고리의 다른 글

구간 칠하기  (0) 2025.04.17
십진수를 2진수로, n진수를 m 진수로 - 진수 변환 [알고리즘/JAVA]  (1) 2025.04.11
날짜와 시간 계산 - 시뮬레이션 [알고리즘]  (1) 2025.04.10
[알고리즘] 비트마스크 (Bitmask)  (1) 2024.12.24
[JAVA] Arrays.sort 와 Collections.sort의 차이  (1) 2024.12.04
'ALGORITHM' 카테고리의 다른 글
  • 십진수를 2진수로, n진수를 m 진수로 - 진수 변환 [알고리즘/JAVA]
  • 날짜와 시간 계산 - 시뮬레이션 [알고리즘]
  • [알고리즘] 비트마스크 (Bitmask)
  • [JAVA] Arrays.sort 와 Collections.sort의 차이
hyeblee
hyeblee
감자감자
  • hyeblee
    hyeblee
    hyeblee
  • 전체
    오늘
    어제
    • 분류 전체보기
      • PS
        • Programmers
        • BAEKJOON
        • CODETREE
      • ALGORITHM
      • JAVA
      • CS
        • 면접을 위한 CS전공지식
      • SPRING
      • 회고
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    상한값
    자바
    반닫힌 구간
    backjoon
    spring #스프링 #스프링부트 #springboot #please sign in
    플레이데이터 백엔드
    16954
    숨바꼭질3
    백트래킹
    플레이데이터 백엔드 후기
    java
    흐른 시간 계산
    java #deque #자바 #덱
    arrays.sort #collections.sort #list.sort #객체정렬 #배열정렬 #timsort #dual pivot quicksort #정렬 #자바
    구간 칠하기
    백준
    하한값
    dfs
    java #스프링부트 #자바버전 #자바 버전 충돌 #jvm
    BOJ
    플레이데이터 백엔드 부트캠프 후기
    왔다 갔던 구역2
    탐색
    BFS
    15652
    날짜와 시간 계산
    플레이데이터 백엔드 부트캠프
    흐른 일수 계산
    알고리즘
    spring #springboot #스프링 #스프링부트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
hyeblee
[Algorithm] 이분탐색 알고리즘 - Upper Bound/Lower Bound
상단으로

티스토리툴바