N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.
첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.
M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.
5
4 1 5 2 3
5
1 3 7 9 5
1
1
0
0
1
시간 초과한 풀이
n=int(input())
lst_n=list(map(int,input().split()))
m=int(input())
lst_m=list(map(int,input().split()))
for mm in lst_m:
left=min(lst_n)
right=max(lst_n)
while left<=right:
mid=(left+right)//2
if mm<=mid:
right=mid-1
answer=mid
else:
left=mid+1
if answer==mm:
print(1)
else:
print(0)
틀렸던 이유
lst_n
에서 탐색한 것이 아니라 lst_n
의 최소값과 최대값 사이의 모든 정수들 중에서 탐색을 했기때문에 시간초과가 일어날 수 밖에 없었다.성공한 풀이
n=int(input())
lst_n=list(map(int,input().split()))
m=int(input())
lst_m=list(map(int,input().split()))
lst_n.sort()
for mm in lst_m:
left=0
right=len(lst_n)
if mm<lst_n[left]:
print(0)
continue
elif mm>lst_n[right-1]:
print(0)
continue
while left<=right:
mid=(left+right)//2
if mm==lst_n[mid]:
break
elif mm<lst_n[mid]:
right=mid-1
else:
left=mid+1
if lst_n[mid]!=mm:
print(0)
else:
print(1)
mid
값을 인덱스로 이용한다.lst_n
에 있는 최소값과 최대값보다 작거나 크면 처음부터 걸러주는 작업을 해준다. -> if문 이용
while
문을 빠져나온 후에 mid
인덱스에 해당하는 리스트 값이 탐색하려는 값과 같으면 1
을 출력하고 아니면 0
을 출력한다.def binary(l, N, start, end):
if start > end:
return 0
m = (start+end)//2
if l == N[m]:
return 1
elif l < N[m]:
return binary(l, N, start, m-1)
else:
return binary(l, N, m+1, end)
위 코드처럼 재귀함수를 이용하여 이분탐색을 할 수도 있다.
다른 사람의 풀이를 서칭하다가 in
을 이용해서 문제를 푼 코드를 봤다.
의문이 들어서 in
을 이용하여 코드를 작성했더니 통과했다. 리스트로 이용해서 in
연산자를 쓰면 시간초과가 발생하고, set으로 변환해준 다음에 in
연산자를 쓰면 시간초과가 발생하지 않고 통과한다!
n=int(input())
lst_n=list(map(int,input().split()))
lst_n=set(lst_n)
m=int(input())
lst_m=list(map(int,input().split()))
for mm in lst_m:
if mm in lst_n:
print(1)
else:
print(0)
list
에서 in
연산자의 시간복잡도는 O(n)
이고
set
에서 in
연산자의 시간복잡도는 평균 O(1)
, 최악의 경우 O(n)
이기 때문에 set
을 이용하여 이 문제를 풀 수 있었다.
in
연산자를 사용할때 set
으로 변환한 후 사용하면 시간복잡도를 줄일 수 있을 것 같다.
이분탐색을 이해하기 위해 풀었던 문제이기 때문에 이분탐색 알고리즘으로 풀었지만 또 하나의 지식을 하나 얻어간다.