시간복잡도
이진 탐색을 진행할 경우 탐색해야할 데이터 수가 절반씩 줄어드므로 수행시간은 \(O(logN)\) 소요된다.
처음 이 말이 이해가 되지 않아 아래와 같이 좀더 풀어서 이해해 보았다.
이진 탐색을 하게되면 데이터 개수가 32개라고 할 때, 찾아야 하는 영역이 32 -> 16 -> 8 -> 4 -> 2 -> 1 형태로 줄어들게 된다. 여기서 수행시간이 \(O(logN)\) 이라고 하는 부분은 아래 그림을 보면 알 수 있다.
코드 구현
재귀함수로 구현
def binary_search(array, target, start, end):
if start > end:
return None
mid = (start + end) // 2
if array[mid] == target:
return mid
elif array[mid] > target:
binary_search(array, target, start, mid - 1)
else:
binary_search(array, target, mid + 1, end)
반복문으로 구현
def binary_search(array, target, start, end):
while start <= end:
mid = (start + end) // 2
if array[mid] == target:
return mid
elif array[mid] > target:
end = mid - 1
else:
start = mid + 1
return None
n, target = map(int, input().split())
array = list(map(int, input().split()))
result = binary_search(array, target, 0, n - 1)
if result == None:
print("원소가 존재하지 않습니다.")
else:
print(result + 1)
문제
부품찾기
p.197 |
-
내 풀이(재귀적 이진 탐색)
n = int(input()) data = list(map(int, input().split())) data.sort() target_num = int(input()) target_list = list(map(int, input().split())) target_list.sort() def binary_search(array, target, start, end): if start > end: return 'no' mid = (start + end) // 2 if array[mid] == target: return 'yes' elif array[mid] > target: return binary_search(array, target, start, mid - 1) else: return binary_search(array, target, mid + 1, end) for value in target_list: result = binary_search(data, value, 0, n - 1) print(result, end=' ')
-
주의해야 할 부분으로
sort()
함수를 사용하는데 본인은 처음에data = data.sort()
와 같은 식으로 사용해서 None 타입이 반환되어 당황하였다. 리스트에 대한sort()
를 적용할 때는 위 코드와 같이 따로 객체를 할당받을 필요는 없다는 것을 명심하자. -
계수정렬 풀이법: 같은 문제를 계수정렬로 푸는 방법도 있다.
# 계수 정렬 풀이법 # 들어오는 데이터가 모두 정수이고, 한번이라도 해당 부분의 값이 채워지면 별다른 처리없이 'yes'를 출력하면 되므로 # 계수정렬로 풀 수 있다. coef_list = [0] * 100001 n = int(input()) data_list = list(map(int, input().split())) m = int(input()) target_list = list(map(int, input().split())) print(target_list) for val in data_list: coef_list[val] += 1 for val in target_list: if coef_list[val] != 0: print('yes', end=' ') else: print('no', end=' ')
-
python에서의
if value in list:
구문을 통해서 매우 쉽게 풀 수도 있다… 이걸 왜 생각 못했을까..n = int(input()) data_list = list(map(int, input().split())) m = int(input()) target_list = list(map(int, input().split())) for val in target_list: if val in data_list: print('yes', end=' ') else: print('No', end=' ')
떡볶이 떡 만들기
- 내 풀이
-
이진 탐색이 어색해서 제한시간안에 풀지는 못했지만, 문제 해설 힌트를 조금 본 뒤 재귀적으로 구현해보았다.
n, m = map(int, input().split()) dduck_list = list(map(float, input().split())) def bineary_search(array, target, start, end): length = 0 if start > end: return None mid = (start + end) // 2 for val in array: if val - mid > 0: # 연산자 우선순위..? 상관없구먼.. length += (val - mid) else: pass if length == target: return mid elif length > target: result = bineary_search(array, target, mid + 1, end) if result != None: return result else: return mid else: result = bineary_search(array, target, start, mid - 1) if result != None: return result else: return mid result = bineary_search(dduck_list, m, 0, max(dduck_list)) print(f"최종 값 {result}")
-
max 함수를 이용해서 search 영역을 결정하는 것과, 재귀함수에서 현재값을 저장하고 있는 부분을 구현하는것이 처음에 생각이 나지 않아 주어진 시간 안에 풀지 못하였다. 이 부분은
None
을 반환하게 한 뒤 상위 함수에서(현재 실행중인 이진 탐색 함수를 호출했던 부모 함수) 현재 값(mid 값)을 반환하게 하는 식으로 구현해서 풀었다.
-
- 정답 코드 (반복문으로 해결)
-
저자에 따르면 재귀적으로 호출하는게 더 귀찮아서 반복문으로 풀었다고 한다.
# 떡의 개수(N)와 요청한 떡의 길이(M)을 입력받기 n, m = map(int, input().split()) # 각 떡의 개별 높이 정보를 입력받기 array = list(map(int, input().split())) # 이진 탐색을 위한 시작점과 끝점 설정 start = 0 end = max(array) # 이진 탐색 수행(반복적) result = 0 while(start <= end): total = 0 mid = (start + end) // 2 for x in array: # 잘랐을 때 떡의 양 계산 if x > mid: total += x - mid # 잘랐는데 양이 부족한 경우 더 많이 자르기 (왼쪽 부분 탐색) if total < m: end = mid - 1 # 떡의 양이 충분한 경우 덜 자르기(오른쪽 부분 탐색) else: result = mid # 아하 이렇게 구현을 해줘야 종료될 때가 result 최대값이겠구나.. start = mid + 1 # 정답 출력 print(result)
-
추가적으로 아래 포스터에 이진 탐색 문제 풀이 및 고찰을 정리해놨다.