Coding Test/Baekjoon

백준/1920번/Java - 수 찾기 (이진탐색)

grogu.... 2023. 10. 5. 16:24

 

https://www.acmicpc.net/problem/1920

 

1920번: 수 찾기

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들

www.acmicpc.net


이진탐색은 배열이 정렬된 상태에서 원하는 값을 찾을 때 사용할 수 있는 알고리즘이다.

 

정렬된 배열의 중앙에 위치한 값을 선택하고, 찾고자 하는 수(target)과 그 크기를 비교한다.

배열 A의 길이가 N이라면 중앙값의 위치(mid)는 0(start) + N-1(end) 을 2로 나눈 수가 된다.

중앙값이 타겟보다 크다면, 찾고자 하는 수는 중앙값 기준으로 왼쪽에 있으므로

다음 탐색에서는 start ~ mid -1 사이에서 타겟을 찾으면 된다. 

 

반대로 중앙값이 타겟보다 작다면, 타겟은 중앙값 기준으로 오른쪽에 있으므로

다음 탐색에서는 mid + 1 ~ end 사이에서 타겟을 찾으면 된다.

 

이러한 탐색을 반복하다가 A[mid] = target이 되는 순간 탐색을 종료하면 된다.

 

단, 반복은 start가 end보다 커지면 중지해야 한다. 

이진 탐색을 계속 반복하다보면 start 포인터와 end 포인터는 점점 가까워지는데 (탐색범위를 점점 좁히니까)

두 포인터가 서로 교차하였다는 것은 더 이상 탐색할 범위가 없다는 뜻이기 때문이다.

 

1920번 문제는 이러한 이진 탐색을 구현하면 쉽게 풀 수 있다.

주어진 배열을 Arrays.sort()하여 오름차순 정렬하고 이진탐색으로 주어진 수들을 찾으면 된다.

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

    static int[] A;
    static int N;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;
        N = Integer.parseInt(br.readLine());
        A = new int[N];
        st = new StringTokenizer(br.readLine());
        for(int i=0; i<N; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }
        Arrays.sort(A); //O(nlogn)
        int M = Integer.parseInt(br.readLine());
        st = new StringTokenizer(br.readLine());
        int start = 0;
        int end = N-1;
        for(int i=0; i<M; i++) {

            int target = Integer.parseInt(st.nextToken());
            if(binarySearch(start, end, target)){
                bw.write("1\n");
            } else {
                bw.write("0\n");
            }
        }

        br.close();
        bw.flush();
        bw.close();
    }

    private static boolean binarySearch(int start, int end, int target) {
        boolean find = false;
        while (start <= end) {
            int mid = (start + end) / 2;
            if(A[mid] > target) {
                end = mid -1;
            }
            else if(A[mid] < target) {
                start = mid + 1;
            }
            else {
                //A[mid] == target
                find = true;
                break;
            }
        }
        return find;
    }
}