문제
N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.
풀이
문제를 정리해보면 [4,6,5,3,2] 라는 배열을 기준으로 [4,7,6,3,2] 배열 안에 있는 각 숫자들이 기준 배열에 포함되어있는지 아닌지를 판단하면 됨
각 배열의 크기가 최대 10^5이기 때문에 최대 10^5^2까지의 시간복잡도가 나올 수 있어서 이중 반복문으로 풀 수는 없음
그래서 이분탐색 알고리즘을 사용해야 하는데, 말 그대로 배열을 이분화(쪼개서)해서 탐색하는 방법
예를 들어 [1,5,7,9,11] 이라는 배열이 있을 때, 9라는 숫자가 포함되었는지를 확인하고 싶다면
일단 시작인덱스, 끝 인덱스를 st=0,en=4로 저장해놓고, 둘의 중간값을 구해서 해당 값을 구해줌
여기서는 mid = 2 , arr[2] = 7이 되는데, 7은 구해야 하는 값인 9보다 작다. 이 말은 0번부터 2번까지의 값은 7보다 작은 값만 존재하기 때문에, 9를 구해야 되는 입장에서는 굳이 탐색할 필요가 없고 , 3번부터 4번까지의 값을 탐색해야 함
그러면 이제 st를 3으로 , end를 4로 놓고 중간값인 3번째의 값을 보면 9가 나오게 됨
정리해보면 시작index와 끝index를 찾고 그 중간지점의 값을 구해서, 목표 값보다 크다면 시작index는 그대로, 끝index를 중간지점-1로 바꾸기
목표 값보다 작다면, 시작index를 중간지점 +1 , 끝index는 그대로 해서 목표값이 나올때까지 반복문을 돌려주면 됨
만약에 포함되어있지 않은 숫자인 6를 구할 때를 살펴보면
시작=0,끝=4,중간=2 arr[2] = 7 -> 6보다 크기 때문에 5는 2번째 이상에서는 없고, 0번째와 1번째사이에 위치한다고 추측할 수 있음
시작=0,끝=1,중간=0 arr[0] = 1 -> 6보다 작기 때문에 5는 0번째 이하에는 없고, 1번째와 1번째 사이에 위치한다고 추측할 수 있음
시작=1 끝=1 중간=1 arr[1] = 5 -> 6보다 작기 때문에 5는 1번째 이하에는 없고, 2번째와 1번째 사이에 위치한다고 봐야 하는데 시작>끝일 수는 없기 때문에 시작>끝이 나온다면 그 수는 포함되어있지 않는 수가 됨
당연히 정렬 되어있는 배열에서만 사용 가능
코드
const arr = input[1].sort((a, b) => a - b);
let result = "";
for (let i of input[3]) {
let [st, en] = [0, input[0] - 1];
while (st <= en) {
let mid = Math.floor((st + en) / 2);
if (arr[mid] === i) {
result += 1 + "\n";
break;
}
if (arr[mid] < i) {
st = mid + 1;
}
if (arr[mid] > i) {
en = mid - 1;
}
}
if (st > en) {
result += 0 + "\n";
}
}
console.log(result);
'코딩테스트 연습' 카테고리의 다른 글
백준 2156 - 포도주 시식 (0) | 2023.05.24 |
---|---|
백준 2606 - 바이러스 (0) | 2023.05.23 |
프로그래머스 - 마법의 엘리베이트 (0) | 2023.04.25 |
백준 1912 - 연속합 (0) | 2023.04.22 |
백준 1182 - 부분수열의 합 (0) | 2023.04.22 |