TIL | 알고리즘 기초 # 4
이진탐색 재귀로 구현해보기
def binary_search(element, some_list, start_index=0, end_index=None):
# end_index가 따로 주어지지 않은 경우에는 리스트의 마지막 인덱스
if end_index == None:
end_index = len(some_list) - 1
# start_index가 end_index보다 크면 some_list안에 element는 없다
if start_index > end_index:
return None
# 범위의 중간 인덱스를 찾는다
mid = (start_index + end_index) // 2
# 이 인덱스의 값이 찾는 값인지 확인을 해준다
if some_list[mid] == element:
return mid
# 찾는 항목이 중간 값보다 작으면 리스트 왼쪽을 탐색해준다
if element < some_list[mid]:
return binary_search(element, some_list, start_index, mid - 1)
# 찾는 항목이 중간 값보다 크면 리스트 오른쪽을 탐색해준다
else:
return binary_search(element, some_list, mid + 1, end_index)
# 테스트 코드
print(binary_search(2, [2, 3, 5, 7, 11]))
print(binary_search(0, [2, 3, 5, 7, 11]))
print(binary_search(5, [2, 3, 5, 7, 11]))
print(binary_search(3, [2, 3, 5, 7, 11]))
print(binary_search(11, [2, 3, 5, 7, 11]))
0
None
2
1
4
Brute Force - 2
def binary_search(element, some_list, start_index=0, end_index=None):
# end_index가 따로 주어지지 않은 경우에는 리스트의 마지막 인덱스
if end_index == None:
end_index = len(some_list) - 1
# start_index가 end_index보다 크면 some_list안에 element는 없다
if start_index > end_index:
return None
# 범위의 중간 인덱스를 찾는다
mid = (start_index + end_index) // 2
# 이 인덱스의 값이 찾는 값인지 확인을 해준다
if some_list[mid] == element:
return mid
# 찾는 항목이 중간 값보다 작으면 리스트 왼쪽을 탐색해준다
if element < some_list[mid]:
return binary_search(element, some_list, start_index, mid - 1)
# 찾는 항목이 중간 값보다 크면 리스트 오른쪽을 탐색해준다
else:
return binary_search(element, some_list, mid + 1, end_index)
# 테스트 코드
print(binary_search(2, [2, 3, 5, 7, 11]))
print(binary_search(0, [2, 3, 5, 7, 11]))
print(binary_search(5, [2, 3, 5, 7, 11]))
print(binary_search(3, [2, 3, 5, 7, 11]))
print(binary_search(11, [2, 3, 5, 7, 11]))
0
None
2
1
4
가능한 모든 방법을 다 시행하는 것
예제 2
가까운 매장 찾기
생각..
# 일단 하나 씩 들어가기 for문 사용
# 중첩문 사용해야 할 거같애 왜냐면 모든 경우의 수 비교할거야
# i j 사이의 거리 구하기 -> 리스트에 저장하기
# 근데 매장 위치를 리턴해주니까 range() 사용
# 계속 최솟값을 구해줘 if 문써서 전의 최소값 현재값 비교해서 i, j 저장하도록
# 제곱근 사용을 위한 sqrt 함수
from math import sqrt
# 두 매장의 직선 거리를 계산해 주는 함수
def distance(store1, store2):
return sqrt((store1[0] - store2[0]) ** 2 + (store1[1] - store2[1]) ** 2)
# 가장 가까운 두 매장을 찾아주는 함수
def closest_pair(coordinates):
distance_list = []
for i in range(len(coordinates)):
for j in range(len(coordinates)):
distance_vlaue = distance(coordinates[i], coordinates[j])
if distance_vlaue != 0:
distance_list.append(distance_vlaue)
min_distance = min(distance_list)
for i in range(len(coordinates)):
for j in range(len(coordinates)):
distance_vlaue = distance(coordinates[i], coordinates[j])
if distance_vlaue == min_distance:
n, m = i, j
result = [coordinates[m], coordinates[n]]
return result
# 테스트
test_coordinates = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
print(closest_pair(test_coordinates))
[(2, 3), (3, 4)]
<모범답안>
# 제곱근 사용을 위한 sqrt 함수
from math import sqrt
# 두 매장의 직선 거리를 계산해 주는 함수
def distance(store1, store2):
return sqrt((store1[0] - store2[0]) ** 2 + (store1[1] - store2[1]) ** 2)
# 가장 가까운 두 매장을 찾아주는 함수
def closest_pair(coordinates):
distance_list = []
# 현재까지 본 가장 가까운 두 매장
pair = [coordinates[0], coordinates[1]]
for i in range(len(coordinates) - 1):
for j in range(i + 1, len(coordinates)):
store1, store2 = coordinates[i], coordinates[j]
# 더 가까운 두 매장을 찾으면 pair 업데이트
if distance(pair[0], pair[1]) > distance(store1, store2):
pair = [store1, store2]
return pair
# 테스트
test_coordinates = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
print(closest_pair(test_coordinates))
예제 3
빗물 받기 계산
def trapping_rain(buildings):
collect_rain = 0
for i in range(1, len(buildings) - 1):
# 왼쪽, 오른쪽 근처 가장 높은 길이
max_left = max(buildings[:i])
max_right = max(buildings[i:])
# 빗물이 고일 수 있는 높이
able_collect = min(max_left, max_right)
# 고여진 빗물의 높이
collect_rain += max(0, able_collect - buildings[i])
return collect_rain
# 테스트
print(trapping_rain([3, 0, 0, 2, 0, 4]))
print(trapping_rain([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]))
10
6
합병정렬
-일반적인 방법으로 구현했을 때 안정 정렬에 속하며, 분할 정복 알고리즘의 하나
-하나의 리스트를 두 개의 균등한 크기로 분할하고 분할된 부분 리스트를 정렬한 다음, 두 개의 정렬된 부분 리스트를 합하여 전체가 정렬된 리스트가 되게하는 방법
합병 정렬의 단계
- Divide : 입력 배열을 같은 크기의 2개의 부분 배열로 분할한다.
- Conquer : 부분 배열을 정렬한다. 부분 배열의 크기가 충분히 작지 않으면
순환 호출
을 이용하여 다시 분할 정복 방법을 적용한다. - Combine : 정렬된 부분 배열들을 하나의 배열에 합병한다.
Author And Source
이 문제에 관하여(TIL | 알고리즘 기초 # 4), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sihaha/TIL-알고리즘-기초-4저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)