백준 1920 - 수 찾기

YongHyun·2023년 4월 26일
0
post-thumbnail

문제

시간 제한 1초
N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.

출력

M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.

예제 입력 1

5
4 1 5 2 3
5
1 3 7 9 5

예제 출력 1

1
1
0
0
1

문제 풀이

N의 최대값은 100,000 이므로 반복문을 이용하여 문제를 푼다면 시간 제한이 나올것 같다.
이러한 여러 데이터 중에서 원하는 값을 찾아낼 때는 이진 탐색을 사용하면 좋을것 같다.

이진 탐색 : 정렬된 데이터에서 원하는 데이터를 찾을 때 사용하는 알고리즘으로 시간 복잡도는 O(nlogn)O(nlogn) 이다.
이진 탐색 과정은

  • 현재 데이터에서 중앙값을 찾는다.
  • 중앙값 > 찾는 데이터 일 때 중앙값을 기준으로 왼쪽에 있는 데이터셋을 선택한다.
  • 중앙값 < 찾는 데이터 일 때 중앙값을 기준으로 오른쪽에 있는 데이터셋을 선택한다.
  • 이렇게 중앙값을 기준으로 데이터를 찾다가 중앙값 == 찾는 데이터일 때 탐색을 종료한다.

예제 입력 1에 입력된 데이터를 기준으로 문제를 풀어보겠다.

  1. N = 5, A[5] 배열에 저장될 데이터들은 4, 1, 5, 2, 3 순이다.
    M = 5 이고 입력된 각 각의 1, 3, 7, 9, 5 데이터가 A에 포함되어 있다면 1을 출력 그렇지 않으면 0을 출력한다.

  2. 중앙값은 인덱스 시작점 부터 끝 인덱스 까지 더한 값에서 2를 나눠주면 된다. 그리고 찾는 값(여기서는 1)과 비교한다. 찾는 값이 중앙값 보다 작기 때문에 왼쪽에 있는 데이터 셋들로 범위를 변경한다.

  3. 중앙값은 (1 + 2)/2 로 1이기 때문에 찾는 값과 같은 수이기 때문에 1을 출력한다.

이런식으로 나머지 찾는 값들도 같은 이진탐색을 이용하면 된다.

이를 코드에 적용해보면 다음과 같다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class 수찾기 {

    static int[] A;

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        A = new int[N];

        StringTokenizer st = new StringTokenizer(br.readLine());
        for(int i = 0; i < N; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }

        Arrays.sort(A); // 이진 탐색을 할때는 배열이 오름차순으로 정렬이 되어 있는 상태여야 한다.

        StringBuilder sb = new StringBuilder();
        int M = Integer.parseInt(br.readLine());
        st = new StringTokenizer(br.readLine());
        for(int i = 0; i < M; i++) {
            int findNumber = Integer.parseInt(st.nextToken());
            sb.append(binarySearch(findNumber)).append("\n");
        }

        System.out.println(sb);
    }

    private static int binarySearch(int num) {
        int start = 0;
        int end = A.length - 1;

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

            if(A[mid] < num) {
                start = mid + 1;
            }else if(A[mid] > num) {
                end = mid - 1;
            }else {
                return 1;
            }
        }
        return 0;
    }
}

회고

이진 탐색 자체는 이해하기 쉬웠지만 막상 구현하려고 보니 헷갈리는 부분도 있었다. 이진 탐색과 관련된 문제도 많이 풀면서 이해해보도록 하겠다.

profile
백엔드 개발자 되기 위한 여정

0개의 댓글