2022. 5. 12. 16:13ㆍTIL💡/Algorithms
분할 정복(Divide & Conquer)
- 분할 정복은 문제를 2개 또는 그 이상의 작은 부분 문제로 나눈 다음 푸는 것(분할)
- 푼 다음에는 다시 합쳐서 정답을 구함(정복)
- 대표적인 분할 정복 알고리즘
📌 퀵 소트
📌 머지 소트
📌 큰 수 곱셈(카라추바 알고리즘)
📌 FFT
✅ DP와 분할정복의 차이
작은 부분 문제가 중복이 되는가?의 차이다
DP는 작은 부분이 중복되기 때문에 메모이제이션으로 중복 제거
분할 정복의 경우에는 중복되지 않기 때문에 한 번씩만 연산하면 된다.
이분 탐색(Binary Search)
정렬되어 있는 리스트에서 어떤 값을 빠르게 찾는 알고리즘
정렬이 전제되어야 한다.
리스트의 크기를 N이라고 했을 때, O(lgN)의 시간이 걸린다.
상한과 하한(Upper & Lower Bound)
- 상한: 큰 수 중 첫 번째 수
- 하한: 크거나 같은 수 중 첫 번째 수
이분 탐색 시에 찾아도 종료하지 않고 left, right를 조정하여 추가 탐색해나가야 한다.
머지 소트(Merge Sort)
- N개를 정렬하는 알고리즘
- N개를 N / 2, N / 2개로 나눈다.
- 왼쪽과 오른쪽을 각각 정렬한다.
- 두 정렬 결과를 합친다.
퀵 소트(Quick Sort)💡
- 평균적인 상황에서 최고의 성능을 자랑하는 알고리즘(O(NlogN))
- 피벗(pivot)을 하나 고른 다음, 그것보다 작은 것은 앞으로 큰 것은 뒤로 보낸다.
- 그 다음 피벗의 앞과 뒤에서 퀵 정렬을 수행
- 최악의 경우에는 O(N^2)이 걸린다.
int choosePivot(int low, int high) {
return low + (high - low) / 2;
}
int partition(int low, int high) {
int pivotIndex = choosePivot(low, high);
int pivotValue = a[pivotIndex];
// 맨 뒤로 보냄
// 피벗 외의 숫자를 모두 정렬의 대상으로 삼기 위해
swap(a[pivotIndex], high);
int storeIndex = low;
//
for(int i = low;i < high;i++) {
if(a[i] < pivotValue) {
swap(a[i], a[storeIndex])
storeIndex++;
}
}
swap(a[storeIndex], a[high]);
return storeIndex;
}
void quicksort(int low, int high) {
if(low < high) {
int pivot = partition(low, high);
quicksort(low, pivot - 1);
quicksort(pivot + 1, high);
}
}
정렬
정렬을 어떻게 활용할 수 있는지에 대해 초점을 맞춘다.
선택, 버블, 삽입, 퀵, 힙, 병합 정렬 등...
O(NlogN)제일 빠른 거 쓰면 된다.
정렬을 직접 구현하는 것보다는 언어에 구현되어 있는 것을 사용하는 것이 좋다.
algorithm 헤더에 있는 std::sort를 쓰면 된다.
Java의 경우 비교하는 방법이 크게 2가지 방법이 있다.
- Comparable: 클래스 내에서 CompareTo를 구현
- Comparator: 별도의 클래스에서 equals와 compare을 구현
- 비교함수를 잘못 만들 경우 런타임 에러 발생 가능성 존재
Stable Sorting
같은 것이 있는 경우에 정렬하기 전의 순서가 유지되는 정렬 알고리즘
O(NlogN)에서는 MergeSort, O(N^2)에서는 Bubble Sort
C++에서는 stable_sort라는 알고리즘이 있다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Person {
int age;
string name;
};
vector<Person> members;
int main() {
int n, age;
string name;
cin >> n;
for(int i = 0;i < n;i++) {
cin >> age >> name;
members.push_back({age, name});
}
stable_sort(members.begin(), members.end(), [](Person a, Person b) {
return a.age < b.age;
});
for(int i = 0;i < n;i++) {
cout << members[i].age<< ' ' << members[i].name << '\n';
}
}
'TIL💡 > Algorithms' 카테고리의 다른 글
[백준] 2933: 미네랄 (0) | 2022.05.12 |
---|---|
[백준] 나머지 합 (0) | 2022.05.12 |
[중급 알고리즘] 그리디 알고리즘 (0) | 2022.05.12 |
[백준] 11053 가장 긴 증가하는 부분 수열 (0) | 2022.05.12 |
[프로그래머스] 정수 삼각형 (0) | 2022.05.12 |