이진탐색과 응용

Kuno17·2023년 4월 26일
0

CS공부

목록 보기
1/17
post-thumbnail

이진탐색(binarySearch)

이진탐색이란 무었인가?

우리가 배열을 선형으로 접근할떄는 Index를 순서대로 조회하게 된다.
하지만 만약 정렬이 되어있는 배열이라면 선형으로 탐색하는 방법보다 빠르게 조회할 수 있다.

  • 다음과 같이 오름차순 정렬된 배열이 있다.
    int arr[] = { 17, 28, 43, 67, 88, 92, 100 };
    이 배열에서 이진 탐색을 이용해서 43을 검색해보자.
  1. 먼저 시작과 끝 인덱스에서 가운데 인덱스의 값을 찾아 볼 수 있다.
  • srart = 0 , End = 7 , Mid = (start+End)/2 = 3
  1. 가운데 인덱스는 3 이며 값은 67이다 이를 검색값과 비교후 검색값보다 크다면 End = Mid-1 즉 처음 검색안 Mid보다 한칸 작은방향으로 End를 설정할 수 있다.
  2. 이 과정을 반복해서 다음 그림과 같이 원하는 값이 있는 인덱스를 얻을 수 있다.

코드로 구현한다면 다음과 같다.

@SpringBootApplication
public class BinaryTestApplication {

    s![](https://velog.velcdn.com/images/rjsgh17/post/85b62926-71ce-4b61-b1a4-7ab8a7ea97db/image.png)
;
    public static void main(String[] args) {
        System.out.println("반복 호출을 이용한 이진 탐색");
        System.out.println("index = " + binarySearch2(43, 0, arr.length - 1)); // 4
        }
        
    // 반복적 탐색
    static int binarySearch2(int key, int low, int high) {
        int mid;

        while (low <= high) {
            mid = low + (high - low) / 2;

            if (key == arr[mid]) {
                return mid;
            } else if (key < arr[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return -1; // 탐색 실패의 경우
    }

결과는 다음과 같다.

반복 호출을 이용한 이진 탐색
index = 2

어떻게 응용할 수 있을까?

  • 이진탐색의 개념자체는 크게 어렵지 않다. 그렇다면 어떻게 이용해볼 수 있을까? 다음 예제 문제를 참조해서 알 수 있었다.

예제 : 떡볶이 떡 만들기

• 오늘 동빈이는 여행 가신 부모님을 대신해서 떡집 일을 하기로 했습니다. 오늘은 떡볶이 떡을 만드는 날입 니다. 동빈이네 떡볶이 떡은 재밌게도 떡볶이 떡의 길이가 일정하지 않습니다. 대신에 한 봉지 안에 들어가 는 떡의 총 길이는 절단기로 잘라서 맞춰줍니다.

• 절단기에 높이(H)를 지정하면 줄지어진 떡을 한 번에 절단합니다. 높이가 H보다 긴 떡은 H 위의 부분이 잘릴 것이고, 낮은 떡은 잘리지 않습니다.
• 예를 들어 높이가 19, 14, 10, 17cm인 떡이 나란히 있고 절단기 높이를 15cm로 지정하면 자른 뒤 떡의 높이는 15, 14, 10, 15cm가 될 것입니다. 잘린 떡의 길이는 차례대로 4, 0, 0, 2cm입니다. 손님은 6cm 만큼의 길이를 가져갑니다.

• 손님이 왔을 때 요청한 총 길이가 M일 때 적어도 M만큼의 떡을 얻기 위해 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하세요

입력조건
• 첫째 줄에 떡의 개수 N과 요청한 떡의 길이 M이 주어집니다.
(1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

• 둘째 줄에는 떡의 개별 높이가 주어집니다. 떡 높이의 총합은 항상 M 이상이므로, 손님은 필요한 양만 큼 떡을 사갈 수 있습니다. 높이는 10억보다 작거나 같은 양의 정수 또는 0입니다.

출력 조건
• 적어도 만큼의 떡을 집에 가져가기 위해 절단기에 설정할 수 있는 높아의 최댓값을 출력합니다

입력 예시 : 고객이 가져온 떡 = {19,15,10,17}, N = 4 , M = 6
출력 예시 : 15

본문제의 출처 및 영상 여기를 참조해주세요 해설도 영상입니다~!!!

사고과정

  1. 구해야하는 값은 결국 (절단 높이 ≤ 고객이 가저가는양) 이때 절단높이의 최대값을 구하라!?

Code

        Scanner sc = new Scanner(System.in);

        //떡의 개수  = N    요청한 떡의 길이 (M)
        int n = sc.nextInt();
        int m = sc.nextInt();

        //r각 떡의 개별 높이 정보
        int[] arr1 = new int[n];
        for (
                int i = 0;
                i < n; i++) {
            arr1[i] = sc.nextInt();
        }

        //이진 탐색을 위한 시작점과 끝점 설정
        int start = 0;
        int end = (int) 1e9; //10억
        //이진 탐색 수행( 반복적 )
        int result = 0;
        while (start <= end) {
            long total = 0;
            int mid = (start + end) / 2;
            for (int i = 0; i < n; i++) {
                //잘랐을 때의 떡의 양 계산
                if (arr1[i] > mid) total += arr[i] - mid;
            }
            if (total < m) { //떡의 양이 부족한 경우 더 많이 자르기 (왼쪽 부분 탐색)
                end = mid - 1;
            } else { // 떡의 양이 충분할 경우 덜 자르기(오른쪽 부분 탐색)
                result = mid; // 최대한 덜 잘랐을 떄를 구하는 내용이므로 현제 mid값을 기록
                start = mid + 1;
            }
        }
        System.out.println(result);
    }

시작점과 끝점을 mid값을 조건에 따라 변경하면서 이분탐색을 진행 할 수 있다. 개념자체는 어렵지 않으나 문제에 이분탐색을 적용하는게 어렵다.

예제를 추가적으로 풀요하다.

profile
자바 스터디 정리 - 하단 홈 버튼 참조.

0개의 댓글