BOJ/수학

1920번: 수 찾기

둠치킨 2022. 1. 13. 23:29

1920번: 수 찾기(BOJ C/C++)

사용 언어: C

문제

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을 출력한다.

 

풀이

문제를 한번 쓱 읽어보면 이중 for문으로 간단하게 풀 수 있을거라고 착각할 수 있지만 이미 백준 문제를 많이 접해본 이상 이렇게 간단히 풀릴 수가 없다. 이중 for문으로 쓰면 시간복잡도는 O(n^2)까지 올라갈 수 있다. 그래서 이분 탐색(이진 탐색)으로 바로 풀 생각을 할 수 있다. 아니면 해시를 사용해서 풀 수도 있겠지만... 아직 해시를 공부한 적이 없기 때문에 언젠가 공부해서 해시 구현 글도 올려보겠다..! 

 

어쨌든 이분 탐색은 시간복잡도가 O(logn)이므로 이중 for문 보다 확실히 빠르고 알아야 할 것이 정렬된 리스트 혹은 배열에서 사용하는 것이므로 입력 받은 배열을 정렬해줘야 한다. 그럼 여기서도 시간복잡도를 따져야하는데 퀵소트가 pivot에 따라 시간복잡도가 최대 O(n^2)일 수 있지만 평균적으로 O(nlogn)이므로 퀵소트를 사용한다. 퀵소트는 그냥 stdlib.h에 있는 qsort 함수를 사용했다.

 

여담으로 밑에 compare(const void *a,~) 에서 const를 붙이는 이유는 이미 고정된 배열 값을 인자로 넘기는데 함수 안에서 이 값을 고의로 혹은 실수로 변경하는 것은 안되서 애초에 컴파일러가 금지하므로 const를 붙여야 오류가 안 뜬다.

#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b)    // 오름차순 비교 함수 구현
{
    int num1 = *(int *)a;    // void 포인터를 int 포인터로 변환한 뒤 역참조하여 값을 가져옴
    int num2 = *(int *)b;    // void 포인터를 int 포인터로 변환한 뒤 역참조하여 값을 가져옴

    if(num1 < num2) //a가 b보다 작을 때는 -1 반환
        return -1;
    
    if(num1 > num2) //a가 b보다 클 때는 1 반환
        return 1;
    
    return 0; //a와 b가 같을 때는 0 반환
}

int binary_search(int num, int arr[], int low, int high)
{
	int mid;
	while (low <= high)
	{
		mid = (low + high) / 2;
		//탐색 성공
		if (num == arr[mid])
			return 1;
		
		// 탐색 범위 재조정 low ~ mid-1
		else if (num < arr[mid])
			high = mid - 1;
		
		// 탐색 범위 재조정 mid+1 ~ high	
		else if (num > arr[mid])
			low = mid + 1;
	}
	return 0;
}

int main(void)
{
    int low,high,mid;
	int N,M;
	scanf("%d",&N);
	int arr[N];
	for(int i=0;i<N;i++)
		scanf("%d",&arr[i]);
	scanf("%d",&M);
	int data[M];
	for(int i=0;i<M;i++)
		scanf("%d",&data[i]);
	low=0;
	high=N;
	qsort(arr, sizeof(arr)/sizeof(int), sizeof(int),compare);
	for(int i=0;i<M;i++)
		printf("%d\n",binary_search(data[i], arr, low, high));
	
    return 0;
}