▶ 문제
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문이 뭔가 아직은 직관적인 느낌이 강해서 그런지 재귀보다는 많이 사용하게 될 것 같다.
반응형