Skip to content

[탐색] #254

@blossun

Description

@blossun

이분탐색

구현

  • st와 en : target이 있는 인덱스로 가능한 범위
탐색 범위 변화 & 값이 존재하지 않는 상태

image

image

코드
    /**
     * 이분 탐색
     * 값이 있으면 1, 없으면 0
     */
    public int binarySearch(int[] arr, int target) {
        Arrays.sort(arr);

        int st = 0;
        int en = arr.length - 1;
        while (st <= en) {
            int mid = (st + en) / 2;
            if (arr[mid] < target) {
                st = mid + 1;
            } else if (arr[mid] > target) {
                en = mid - 1;
            } else {
                return 1;
            }
        }
        return 0;
    }

문제

#253

이분탐색 활용

  • 배열에 target이 여러 번 들어있을 경우, 제일 왼쪽의 인덱스 혹은 제일 오른쪽의 인덱스를 반환
  • target이 삽입되어도 오름차순 순서가 유지되는 제일 왼쪽/오른쪽의 인덱스를 찾는 문제
    ⇒ 오름차순 순서가 유지되는 제일 왼쪽/오른쪽의 인덱스의 차이 == 해당 배열 내에 target의 등장 횟수

구현

  • st와 en : target이 있는 모순이 생기지 않는 인덱스로 가능한 범위
구현
  • list가 [1, 2, 3]이고 target이 4일 때 target을 index 3에 삽입해야함을 알 수 있습니다.
    즉, 가장 오른쪽이 len-1이 아니라 len이기 때문에 처음에 en을 len으로 둡니다.

image

  • 인덱스는 mid 이하에 존재한다는 사실을 기록하고 다음 단계를 진행 == 이는 곧 en = mid 로 변경이 가능함을 의미

image

image

image

탐색 범위 변화
  1. 제일 왼쪽 인덱스 구하는 과정
    image

  2. 제일 오른쪽 인덱스 구하는 과정
    image

구현 시 주의사항
  • 잘못된 mid 선택으로 무한루프에 빠질 수 있다.
  • st와 en이 1 차이가 나는 경우

image
image
image
image
image

  • en-st 가 어느 정도 이하로 줄어들면 그 안에서는 선형으로 탐색하도록 구현
    image

LowerBound & UpperBound

구현 코드
    /**
     * target이 arr에 들어갔을 때, 정렬이 유지되는 제일 왼쪽 index를 구한다.
     * @param arr : 정렬된 배열이어야 한다.
     * @param target
     * @return
     */
    public int lower_index(int[] arr, int target) {
        int st = 0;
        int en = arr.length; // arr.length -1 이 아님을 주의
        while (st < en) {
            int mid = (st + en)/2;
            if (arr[mid] < target) {
                st = mid + 1;
            } else if (arr[mid] >= target) {  //arr[mid] = target인 경우 en을 옮겨준다.
                en = mid;
            }
        }

        // 값을 찾는게 아니라 값이 들어갈 수 있는 제일 왼쪽 index를 구하는 것이므로..
        return st; //st = en으로 가능한 후보가 1개로 확정될 경우 while문을 탈출함
    }

    /**
     * target이 arr에 들어갔을 때, 정렬이 유지되는 제일 오른쪽 index를 구한다.
     * @param arr : 정렬된 배열이어야 한다.
     * @param target
     * @return
     */
    public int upper_index(int[] arr, int target) {
        int st = 0;
        int en = arr.length; // arr.length -1 이 아님을 주의
        while (st < en) {
            int mid = (st + en)/2;
            if (arr[mid] <= target) { //arr[mid] = target인 경우 st를 옮겨준다.
                st = mid + 1;
            } else if (arr[mid] > target) {
                en = mid;
            }
        }

        // 값을 찾는게 아니라 값이 들어갈 수 있는 제일 왼쪽 index를 구하는 것이므로..
        return st; //st = en으로 가능한 후보가 1개로 확정될 경우 while문을 탈출함
    }

문제

#255

Arrays.binarySearch()

Arrays.binarySearch( 정렬된 배열, 검색할 값); -- 반환타입 int

사용 코드
    @Test
    void case02() {
        int[] arr = {4, 2, 1, 5, 3};
        Arrays.sort(arr);
        int index = Arrays.binarySearch(arr, 1); //정렬된 배열을 넘겨야 한다.
        System.out.println(index); //0
        index = Arrays.binarySearch(arr, 2);
        System.out.println(index); //1
        index = Arrays.binarySearch(arr, 3);
        System.out.println(index); //2
        index = Arrays.binarySearch(arr, 4);
        System.out.println(index); //3
        index = Arrays.binarySearch(arr, 5);
        System.out.println(index); //4
        assertTrue(Arrays.binarySearch(arr, 10) < 0);
    }

최단 경로

Metadata

Metadata

Assignees

No one assigned

    Labels

    Refer★별★공부한 내용 다시 보기

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions