알고리즘 4강을 보며 배운내용
분할정복 알고리즘 2탄
복습
- 순환적으로 문제를 하향식 접근으로 푼다
- 분할 - 정복 - 결합으로 문제를 푼다
- 분할된 문제는 크기만 작고 원래 문제와 같다
오늘은 합병정렬과 선택문제
합병 정렬
분할 정복 방법으로 정렬
분할, 정복, 결합을 잘 지키는 정렬
n만큼 저장장소(왼쪽배열, 오른쪽배열)가 필요하다
⌛ 시간 복잡도
O(nlogn)
✨ 방법
- 분할: 동일한 크기로 나누기
- 정복: 부분배열을 순환적으로 정렬
- 결합: 합병해서 정렬된 배열 만든다
🤖 코드
// 합병 정렬 JavaScript
function mergeSort(원배열, 길이) {
if(n > 1) {
let mid = Math.ceil(길이 / 2)
let 왼쪽배열 = mergeSort(원배열[0 .. mid - 1], mid)
let 오른쪽배열 = mergeSort(mergeSort[mid .. 길이 - 1], 길이 - mid)
원배열 = merge(왼쪽배열, 오른쪽배열, mid, n - mid)
}
return 원배열;
}
// merge JavaScript
function merge(왼쪽배열, 오른쪽배열, n, m) {
let i, j, k = 0;
// 비교해서 작은값 원배열로 이동
while(i < n && j < m){
if(왼쪽배열[i] <= 오른쪽배열[j]) {
원배열[k++] = 왼쪽배열[i++]
} else {
원배열[k++] = 오른쪽배열[j++]
}
}
// 남은 왼쪽, 오른쪽 배열 원배월 맨 뒤로 붙이기
for(i; i<n; i++){
원배열[k++] = 왼쪽배열[i]
}
for(j; j<m; j++) {
원배열[k++] = 오른쪽배열[j]
}
return 원배열
}
선택 문제
배열에서 i번째 작은 원소 찾는 문제
최솟값, 중간값, 최댓값 찾을 수 있다
여러 방법들
오름차순 정렬하고 i번째 원소 찾는 방법 => O(nlogn)
최솟값 찾는 i번 반복 => O(n제곱)
⌛ 시간복잡도
O(n)
✨ 방법
항상 반으로 부분배열이 나눠지도록 피벗 선택
피벗 선택 방법(중간값들의 중간값 찾기)
- 크기 n 배열을 5개씩 묶어서 n/5개 그룹 만든다
- 마지막에 5개 그룹 안된 원소 그대로 남겨둔다
- 각 그룹에 중간값 찾고,
- 중간값 중에서 또 중간값 찾는다 => 피벗
pseudo 코드
function selection(원배열, 길이, 찾고 싶은 i번째) {
if(길이 <= 5) {
원배열에서 i번째 원소 찾아서 return
} else {
원배열 5개씩 묶어서 그룹 생성
각 그룹 중간값 구하고, 이들로 중간값배열 구성
피벗(중간값의 중간값) 계산하려고 선택함수 재귀 호출
pivot = selection(중간값배열, 그룹갯수, 그룹갯수/2)
피벗 사용해서 원배열 분할
if( i == j + 1 ) {
return 원배열
} else if( i < j + 1 ) {
selection(원배열[0 .. j - 1], j, i)
} else {
selection(원배열[j + 1 .. 길이 - 1], 길이 - j - 1, i - j - 1)
}
}
}
퀵 정렬의 partition()이용할 수 있는데
시간복잡도 O(n제곱)
'Computer Science > Algorithm :: 알고리즘' 카테고리의 다른 글
알고리즘 6강 :: 동적 프로그래밍 점화식, 편집 거리, 최단 경로 (0) | 2022.03.01 |
---|---|
알고리즘 5강 :: 동적 프로그래밍 알고리즘 원리, 연쇄 행렬 곱셈 (0) | 2022.02.28 |
알고리즘 3강 :: 분할정복, 이진탐색, 퀵정렬 (0) | 2022.02.25 |
알고리즘 2강 :: 대표적인 알고리즘 3가지, 점근 성능 (0) | 2022.02.24 |
알고리즘 1강 :: 모든 자료구조 구현은 배열과 연결리스트 (0) | 2022.02.22 |