숫자 카드
https://www.acmicpc.net/problem/10815
문제
숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 가지고 있는지 아닌지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다. 두 숫자 카드에 같은 수가 적혀있는 경우는 없다.
셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 가지고 있는 숫자 카드인지 아닌지를 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다
출력
첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 가지고 있으면 1을, 아니면 0을 공백으로 구분해 출력한다.
예제 입력 1
5
6 3 2 10 -10
8
10 9 -5 2 3 4 5 -10
예제 출력 1
1 0 0 1 1 0 0 1
코드
import sys
input = sys.stdin.readline
n = int(input())
card = list(map(int, input().split()))
card.sort()
m = int(input())
res = list(map(int, input().split()))
for num in res:
tmp = 0
start, end = 0, n-1
while start <= end:
mid = (start + end) // 2
if card[mid] < num:
start = mid + 1
elif card[mid] > num:
end = mid - 1
else:
tmp = 1
break
print(tmp, end = ' ')
풀이
우선 문제를 보았을 때 for문을 돌며 if문과 in 연산자를 활용하여 완전 탐색하는 방식으로 문제를 구현했으나 예상한 것처럼 시간복잡도에서의 효율이 떨어져 시간초과가 발생하였다.
결국 가지고 있는 숫자 카드를 전부 비교하는 게 아닌 이진 탐색을 이용하여 범위를 반으로 줄여가며 카드 소유 여부를 판단해야 겠다고 생각하였다.
우선, for문을 돌면서 tmp라는 변수에 카드 소유 여부를 최종적으로 출력할 것이다. start는 첫 번째 인덱스 번호인 0, end는 마지막 인덱스 번호인 n-1이다. 이 때 중앙값인 mid를 인덱스로 가지는 소유 카드 번호를 숫자 num와 비교해가며 범위를 줄여나간다. 그리고 소유 카드 번호와 num이 일치하면 tmp = 1로 할당해준다.
예시를 통해 살펴보자. 우선 정렬한 card = [-10, 2, 3, 6, 10]이다.
1번째 num인 10에서의 1번째 반복
tmp = 0, start = 0, end = 4, mid = 2, card[mid] = 3이므로, card[mid] < num 이므로 start = mid + 1 = 2 + 1 = 3이 된다.
1번째 num인 10에서의 2번째 반복
tmp = 0, start = 3, end = 4, mid = 3, card[mid] = 6이므로, card[mid] < num이므로 start = mid + 1 = 3 + 1 = 4이 된다.
1번째 num인 10에서의 3번째 반복
tmp = 0, start = 4, end = 4, mid = 4, card[mid] = 10이므로, card[mid] == num이므로 tmp = 1을 할당해주고 while 반복문을 탈출한 후, tmp = 1을 출력한다.
2번째 num인 9에서의 1번째 반복
...
이렇게 반복하면 카드를 전부 비교하지 않고 더욱 효율적으로 카드 소유 여부를 알아낼 수 있다.
'Python > Coding Test' 카테고리의 다른 글
[백준] 2875 : 대회 or 인턴 (0) | 2023.11.15 |
---|---|
[알고리즘] 분할정복 (0) | 2023.11.14 |
[백준] 2110 : 공유기 설치 (0) | 2023.11.13 |
[백준] 1654 : 랜선 자르기 (1) | 2023.11.13 |
[알고리즘] 이분탐색 (Binary Search) (0) | 2023.11.13 |