본문 바로가기

공부

(7)
확장 유클리드 호제법 (Extended Euclidean Algorithm) 1. 정의 확장 유클리드 호제법은 두 정수 $a, b$에 대해 $GCD(a, b) = d$라고 했을 때, $ax + by = d$를 만족하는 $x, y$를 찾을 때 이용되는 알고리즘이다. 확장 유클리드 호제법에 대해 공부하기 전에 유클리드 호제법과 베주 항등식이 무엇인지 먼저 알아보자. 1) 유클리드 호제법 두 정수 $a, b$에 대하여 최대공약수 $GCD(a, b)$를 빠르게 찾는 알고리즘이다. $a$를 $b$로 나눈 나머지를 $r$이라고 할 때, $GCD(a, b) = GCD(b, r)$이 성립하는데 유클리드 호제법은 이 성질을 이용한다. 아래와 같이 한 숫자에서 다른 숫자를 계속 나누어서 나머지가 0이 될 때까지 위 성질을 이용하면 몇 번의 연산만으로 $GCD(a, b)$를 구할 수 있다. $a$를..
인덱스 트리 (Binary Indexed Tree) 1. 정의 인덱스 트리는 원소들의 구간 합을 빠르게 구하기 위해 사용하는 자료구조로 펜윅 트리라고도 한다. 세그먼트 트리와 같이 기능을 하지만 구현이 좀 더 쉽고 직관적이며 많은 문제에 활용할 수 있다. 인덱스 트리는 원소를 업데이트(Point update)하거나 구간 합(Range query)을 구하는 데 걸리는 시간은 $O(logN)$이다. 2. 구현 1) 배열 크기 설정 인덱스 트리는 포화 이진트리로 먼저 배열의 크기를 구해야 한다. 단순히 배열에 원소만 들어가는 것이 아니라 원소들의 구간합 정보가 배열에 포함되어야 한다. 인덱스 트리의 리프 노드에 원소가 저장이 되어야 하고, 리프 노드부터 루트 노드까지 각각의 부모 노드는 자식 노드들의 합이 저장되어야 한다면 구현에 필요한 노드의 개수 즉, 인덱..
백트래킹 (Backtracking) 백트래킹이란 경로를 탐색하다가 올바르지 않은 경로라면 계속해서 탐색하는 것이 아니라 이전 단계로 돌아가 다시 올바른 경로를 향해 찾아가는 알고리즘이다. 모든 경로를 탐색하는 알고리즘인 DFS를 이용하지만, 조건에 맞지 않는 경로는 제외시킨다는 점에서 조금 더 효율적이다. 여기서 경로를 제외시키는 것을 가지치지(pruning)이라고 한다. 가지치기를 하기 위한 조건을 얼마나 잘 설정하느냐에 따라 시간복잡도가 천차만별이다. 백트래킹 알고리즘은 대표적으로 순열, 조합을 구하는 것에 이용된다. 1. 순열 (중복x) ● 코드 #include #include #include #include #include #include #include #include #include #include #include #includ..
카운팅 정렬 (Counting Sort) ● 코드 #include #include #include #include using namespace std; using ll = long long; using ii = pair; vectorarr(10001); int main() { // 입력 int N; cin >> N; for (int i = 0; i > n; // 카운팅 정렬 arr[n]++; } // 출력 for (int i = 0; i < arr.size(); i++) { if (arr[i]) { while (arr[i]--) cout
병합 정렬 (Merge Sort) ● 코드 #include #include #include #include using namespace std; using ll = long long; using ii = pair; vectorarr(1000000); vectortemp(1000000); void mergesort(int start, int end); // 분할 void merge(int start, int mid, int end); // 정복 int main() { // 입력 int N; cin >> N; for (int i = 0; i > arr[i]; // 병합 정렬 mergesort(0, N - 1); // 출력 for (int i = 0; i < N; i++) cout
삽입 정렬 (Insertion Sort) ● 코드 #include #include #include #include using namespace std; using ll = long long; using ii = pair; int main() { // 입력 int N; cin >> N; vectorarr(N); for (int i = 0; i > arr[i]; // 삽입 정렬 for (int i = 1; i < N; i++) { int temp = arr[i]; int idx = i - 1; while (0
버블 정렬 (Bubble Sort) ● 코드 #include #include #include #include using namespace std; using ll = long long; using ii = pair; int main() { // 입력 int N; cin >> N; vectorarr(N); for (int i = 0; i > arr[i]; // 버블 정렬 for (int i = 0; i arr[j]) swap(arr[i], arr[j]); } } // 출력 for (int i = 0; i < N; i++) cout