Python 병합정렬 알고리즘
테스트를 보는 곳이나 면접에서도 직접 구현해보라고 하는 구현방법들이다.
병합 정렬은 배열의 앞부분과 뒷부분의 두 그룹으로 나누어 각각 정렬한 후 병합하는 작업을 반복하는 알고리즘.
예를 들어서
A - 1, 2, 3, 5
B - 4, 6, 7, 8
이 두 집합을 합쳐가면서 정렬하는 방법
병합
# 병합
array_a = [1, 2, 3, 5]
array_b = [4, 6, 7, 8]
def merge(array1, array2):
result = []
array1_index = 0
array2_index = 0
while array1_index < len(array1) and array2_index < len(array2):
# index값이 커질 때 즉 한 바퀴 다 돌 때 탈출조건
if array1[array1_index] < array2[array2_index]:
# array1[0]과 array2[0]의 비교, 즉 1과 4의 비교
result.append(array1[array1_index])
# 만약 array1이 작다면 array1의 0번쨰 인덱스를 빈리스트 result에 붙인다.
array1_index += 1
# array1은 한번 갔으니, index를 +1해준다. 그럼 다음에 비교할떈 array1[1]이 되겠지.
else:
result.append(array2[array2_index])
array2_index += 1
# 아닐 경우는 그 반대로 해준다.
if array1_index == len(array1):
while array2_index < len(array2):
result.append(array2[array2_index])
array2_index += 1
#만약에 array1_index값이 array1의 범위와 똑같아 진다면, 즉 한 바퀴 다 돌았는데
# array2는 아직 전부 못돌았으면, 그냥 남은 모든 array2의 리스트를 result에 붙여넣어준다.
# array2_index가 1씩 커지다 결국 while문 탈출
if array2_index == len(array2):
while array1_index < len(array1):
result.append(array1[array1_index])
array1_index += 1
# 이건 그 반대의 경우다. 즉 array1이 범위를 다 못돌았을 때
return result
# 정렬한 result 값을 출력해준다.
print(merge(array_a, array_b))
[1 , 2, 3, 5]
[4, 6, 7, 8]
먼저 1과 4를 비교하고
1 < 4 이므로 1을 빈리스트 C에 넣는다.
그렇게 5까지 반복하다 5가 작아지면 4가 5보다 작으므로 이번엔 4를 C에넣는다.
그 후엔 5와 6을 비교하고 5를 C에 넣는다.
남은 6, 7, 8 은 하나씩 C에 추가해준다.
병합정렬
# 병합정렬
array = [5, 3, 2, 1, 6, 8, 7, 4]
def merge_sort(array): # N만큼의 시간복잡도
if len(array) <= 1:
return array
# 만약에 [5]가 들어오면 더 이상 정렬을 해야될 필요가 없다. 이미 정렬된 상태니까
mid = len(array) // 2
left_array = merge_sort(array[:mid]) #재귀의 방식으로 계속 쪼갠다.
#0부터 시작해서 mid까지, 반을 쪼개서 왼쪽에 있는것만 반환됨
right_array = merge_sort(array[mid:])
#오른쪽 절반
return merge(left_array, right_array)
#바로 밑의 merge 함수를 이용해서 합쳐줌 (병합 해 줌)
def merge(array1, array2):
# len(array1) + (array2)
# = O(N) 시간
result = []
array1_index = 0
array2_index = 0
while array1_index < len(array1) and array2_index < len(array2):
if array1[array1_index] < array2[array2_index]:
result.append(array1[array1_index])
array1_index += 1
else:
result.append(array2[array2_index])
array2_index += 1
if array1_index == len(array1):
while array2_index < len(array2):
result.append(array2[array2_index])
array2_index += 1
if array2_index == len(array2):
while array1_index < len(array1):
result.append(array1[array1_index])
array1_index += 1
return result
print(merge_sort(array)) # [1, 2, 3, 4, 5, 6, 7, 8] 가 되어야 합니다!
분할 정복의 개념
분할 정복은 문제를 작은 2개의 문제로 분리하고, 각각을 해결한 다음, 결과를 모아서 원래의 문제를 해결하는 전략.
예를 들어 [5. 4] 라는 배열이 있다면,
이 배열을 [5]와 [4]를 가진 각각의 배열로 작은 2개의 문제로 분리해서 생각하는 것.
이 둘을 합치면서 정렬하면 결국 전체의 정렬된 리스트를 볼 수 있다.
MergeSort(0, N) = Merge(MergeSort(0, N/2) + MergeSort(N/2, N))
0부터 N까지 정렬한걸 보기 위해서는 0부터 N/2까지 정렬한 것과 N/2부터 N까지 정렬한걸 합치면 된다는 개념.
'Back > Algorithm' 카테고리의 다른 글
Python 백준 1874 스택수열 알고리즘 (0) | 2021.03.10 |
---|---|
Python 백준 4949 균형잡힌세상 / 스택 알고리즘 (0) | 2021.03.10 |
Python 백준 2805 나무자르기 / 이진탐색 알고리즘 (0) | 2021.03.09 |
Python 백준 11651 좌표정렬하기2 / 파이썬 알고리즘 (0) | 2021.03.09 |
Python 재귀함수 알고리즘 - 백준 11729 하노이탑 (0) | 2021.03.09 |