백준 알고리즘/이분 탐색

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

Sun720 2022. 7. 7. 00:08

▶ 문제

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

 

 설명

백준의 단계별 문제에서 이진 탐색의 첫 문제이다.

낯선 개념이기 때문에 유튜브를 통해 이진탐색 알고리즘에 대해서 먼저 이해한 후에

이 문제를 접근해 보았다.

 

이 문제는 N개의 원소를 갖는 배열 중에서 찾고자 하는 수가 있으면 1을, 없으면 0을 반환하는 문제이다.

 

이진 탐색을 하기 위해서는 책 속의 페이지처럼 오름차순으로 정렬되어 있어야 한다.

이름에서 알 수 있듯, 정렬된 배열의 원소를 반으로 뚝 나누어서

찾으려는 수가 왼쪽에 속한다면 오른쪽은 버리는 식으로

검색을 할 필요가 없는 부분을 제거하도록 하면 된다.

 

이진 탐색은 반복문과 재귀호출, 이렇게 두 가지 방법으로 풀 수 있다.

 

문제 풀이

🌱 풀이1.  반복문 구현

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

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st;

		int N = Integer.parseInt(br.readLine());
		int arr[] = new int[N];
		st = new StringTokenizer(br.readLine(), " ");
		for (int i = 0; i < arr.length; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr); // 오름차순 정렬

		int M = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine(), " ");
		while (M-- > 0) {
			int target = Integer.parseInt(st.nextToken());
			sb.append(binarySearch(arr, target, 0, N - 1)).append("\n");
		}
		System.out.println(sb);

	}

	private static int binarySearch(int[] arr, int target, int start, int end) {

		while (start <= end) {
			int mid = (start + end) / 2;
			if (arr[mid] == target) {
				return 1;
			} else if (arr[mid] > target) {
				end = mid - 1;
			} else {
				start = mid + 1;
			}
		}

		return 0;
	}
}

 

 

 

🌱 풀이2. 재귀 구현

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

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st;

		int N = Integer.parseInt(br.readLine());
		int arr[] = new int[N];
		st = new StringTokenizer(br.readLine(), " ");
		for (int i = 0; i < arr.length; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr); // 오름차순 정렬

		int M = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine(), " ");
		while (M-- > 0) {
			int target = Integer.parseInt(st.nextToken());
			sb.append(binarySearch(arr, target, 0, N - 1)).append("\n");
		}
		System.out.println(sb);

	}

	private static int binarySearch(int[] arr, int target, int start, int end) {

		if (start > end) {
			return 0;
		}
		int mid = (start + end) / 2;
		if (arr[mid] == target) {
			return 1;
		} else if (arr[mid] > target) {
			return binarySearch(arr, target, start, mid - 1);
		} else {
			return binarySearch(arr, target, mid + 1, end);
		}

	}
}

 

 

 

Log

 

위 : 재귀로 구현

아래 : while 문으로 구현

 

재귀와 while 문의 차이는 그리 많이 나지 않았다. DP 의 메모이제이션이 아닌 이상 재귀가 아닌 방식과 재귀로 구현한 방식이 크게 차이가 나지 않는 것 같다.

while문이 뭔가 아직은 직관적인 느낌이 강해서 그런지 재귀보다는 많이 사용하게 될 것 같다.

 

반응형