백준풀이

[백준/자바] 1920번: 수 찾기

요빈 2023. 5. 17. 11:20

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


이 문제를 처음 보고 든 생각난 풀이는 그냥 배열을 리스트로 변환한 후 contains를 사용하는 것이었다. 

되게 간단한 문제같은데 정답률이 30%도 안되는 걸 보고 "이렇게 푸는건 아니구나" 싶었다.

 

처음 작성한 코드는 다음과 같다.

import java.io.*;
import java.util.*;

public class Boj_1920 {

	public static void main(String[] args) throws NumberFormatException, IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		Integer [] arr = new Integer[N];
		
		for(int i = 0; i<N; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		
		int M = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		ArrayList<Integer> list = new ArrayList<>(Arrays.asList(arr));
		
		for(int i = 0; i<M; i++) {
			if(list.contains(Integer.parseInt(st.nextToken())))
				System.out.println(1);
			else
				System.out.println(0);
		};
	}
}

 

역시나 "시간초과"가 떴고, 문제를 다시 읽어보니 N, M의 범위가 100,000 까지였다.

즉, 최악의 경우엔 반복문을 10 ^ 10번 실행해야한다는 뜻이다.

따라서 빠르게 값을 찾는 방법이 필요했고, 이진탐색으로 해결하였다. 

자바에서 이진탐색을 사용하는 방법은 두 가지가 있다.

 

  • 직접 구현
  • Arrays.binarySearch 사용

두 방법을 모두 이용해 풀어보았다.

 

1. 직접 구현

 

이진 탐색 전에 배열 정렬해주기!

import java.io.*;
import java.util.*;

public class Boj_1920 {

	public static void main(String[] args) throws NumberFormatException, IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		int [] arr = new int[N];
		
		for(int i = 0; i<N; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		
		int M = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		Arrays.sort(arr);
		for(int i = 0; i<M; i++) {
			int num = Integer.parseInt(st.nextToken());
			System.out.println(binSearch(num, arr));
		};
	}
	
	static int binSearch(int x, int[] arr) {
		int start = 0;
		int end = arr.length-1;
		while(start <= end) {
			int mid = (start + end) / 2;
			if(arr[mid] > x) {
				end = mid - 1;
			}else if(arr[mid] < x) {
				start = mid + 1;
			}else
				return 1;
		}
		return 0;
	}
}

 

2. 라이브러리 사용

import java.io.*;
import java.util.*;

public class Boj_1920 {

	public static void main(String[] args) throws NumberFormatException, IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		int [] arr = new int[N];
		
		for(int i = 0; i<N; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		
		int M = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		Arrays.sort(arr);
		for(int i = 0; i<M; i++) {
			int num = Integer.parseInt(st.nextToken());
			if(Arrays.binarySearch(arr, num)>=0)
				System.out.println(1);
			else
				System.out.println(0);
		};
	}
}

 

실행 결과는 다음과 같다.

아래가 직접 구현 / 위가 라이브러리 사용했을 때의 결과이다.

 

 

결론은

범위가 클 때 특정 값을 찾아야할 경우 이진탐색을 사용하자!