알고리즘 - Binary Search

this-is-spear·2023년 2월 12일
0

Binary Search은 무엇인지

  • Binary Search 알고리즘은 정렬된 배열에서 원소를 찾을 때까지 반복적으로 배열의 반씩 나누어 탐색 범위를 줄이는 방식이며, 탐색 속도는 O(logn)O(log n)입니다.
  • Linear 검색의 시간복잡도인 O(n)O(n) 보다 빠르고 사용하는 메모리도 비슷하기 때문에 Binary Search는 효율적인 탐색 방법입니다.

이진 탐색의 탐색 시간을 시간 복잡도로 증명

일부 m>=1m >= 1에 대해 T(m)=O(logm)T(m) = O(log m)이라 가정할 때, 아래와 같이 표현할 수 있습니다.

T(2m)=T(m)+1=O(logm)+1=O(log2m)T(2m) = T(m) + 1 = O(logm) + 1 = O(log2m)

즉, 모든 n>=1n >= 1에 대해 T(n)=O(logn)T(n) = O(log n)이라는 결론을 내릴 수 있습니다.

Binary Search 활용

Binary Search를 이용해 해결할 수 있는 문제는 많습니다. 공통적으로 크기가 다른 여러 개의 선택지에서 적합한 원소를 찾는 경향있습니다.

  • 원소가 존재하는지 판단 가능
  • 일치하는 원소 개수 판단 가능
  • 범위 검색 가능

Binary Search 구현

  • 중간 원소와 찾는 원소의 크기를 비교해나가며 탐색 범위를 줄입니다.
  • startend의 원소를 변경할 때, 무한 루프가 발생하지 않도록 주의해야 합니다.
class BinarySearch {

  int[] arr;

  public BinarySearch(int[] arr) {
    Arrays.sort(arr);
    this.arr = arr;
  }

  public boolean binarySearch(int target) {
    int start = 0;
    int end = arr.length - 1;

    while (start <= end) {
      int mid = (start + end) / 2;

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

      if (target < arr[mid]) {
        end = mid - 1;
      } else {
        start = mid + 1;
      }
    }

    return false;
  }
}  

Binary Search 구현 활용 - 일치하는 원소 개수 판단

  • scanLeftElementEqualsOrOver() 메서드는 찾는 원소와 같거나 큰 원소 중 배열 가장 왼쪽에 있는 원소를 반환합니다.
  • scanRightElementEqualsOrBelow() 메서드는 찾는 원소와 같거나 작은 원소 중 배열 가장 오른쪽에 있는 원소를 반환합니다.
  • 두 원소의 인덱스 값을 빼면 일치하는 원소의 개수가 몇개인지 판단이 가능합니다.
class BinarySearchForRangeScan {

    int[] arr;

    public BinarySearchForRangeScan(int[] arr) {
      Arrays.sort(arr);
      this.arr = Arrays.copyOf(arr, arr.length + 1);
    }

    private int scanRightElementEqualsOrBelow(int target) {
      int start = 0;
      int end = arr.length;

      while (start < end) {
        int mid = (start + end) / 2;
        if (arr[mid] > target) {
          end = mid;
        } else {
          start = mid + 1;
        }
      }
      return start;
    }

    private int scanLeftElementEqualsOrOver(int target) {
      int start = 0;
      int end = arr.length;

      while (start < end) {
        int mid = (start + end) / 2;
        if (arr[mid] >= target) {
          end = mid;
        } else {
          start = mid + 1;
        }
      }
      return start;
    }
  }

Binary Search 말고 다른 탐색 방법은 무엇이 있는지

  • 순차적으로 탐색합니다.
  • 탐색 시간 복잡도 : O(n)O(n)
  • 수식을 사용해 원소의 위치를 추정해 비교 횟수를 줄입니다.
  • 탐색 시간 복잡도 : O(log(logn))O(log(logn))
  • 값이 균일하게 분포되는 경우 좋은 성능을 보이지만, 최악의 경우 O(n)O(n)이 걸립니다.
  • 특정 크기 단계로 목록을 건너뛰고 동작하게 됩니다.
  • 탐색 시간 복잡도 : O(n)O(\sqrt{n})
  • 검색 키가 상주하는 범위를 결정하고 해당 범위에서 Binary Search를 진행합니다.
  • 탐색 시간 복잡도 : O(logn)O(log n)
  • Binary Search 과 동작이 비슷하며 두 개로 나누는 것이 아닌 세 개로 나누어서 대상을 확인합니다.
  • 탐색 시간 복잡도 : O(log3n)O(log_3n)

문제

백준

리트 코드

마지막으로

Binary Search 란

정렬된 배열에서 원소를 찾을 때까지 반복적으로 배열의 반을 나누는 방식으로 동작하며 탐색 속도는 O(logn)O(log n)입니다.

Binary Search 만의 장점은 무엇인지

  • 순차적 검색보다 효율적이며 쉽고 구현이 간단합니다.
  • 데이터가 많아져도 성능이 많이 떨어지지 않습니다.
  • 배열, 연결 리스트, 트리 등 다양한 자료구조에서 적용 가능합니다.
profile
익숙함을 경계하자

0개의 댓글