주요 알고리즘 패턴별 예제
- 재귀: 병합 정렬 병합 정렬은 배열을 반으로 나눈 후 정렬된 부분들을 병합하는 전형적인 재귀 알고리즘이다.
#include<iostream>
#include<vector>
using namespace std;
vector<int> data;
vector<int> temp(1000);
void mergeSort(int left, int right) {
if (left >= right) return;
int mid = left + (right - left) / 2;
mergeSort(left, mid);
mergeSort(mid + 1, right);
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
if (data[i] <= data[j]) {
temp[k++] = data[i++];
} else {
temp[k++] = data[j++];
}
}
while (i <= mid) temp[k++] = data[i++];
while (j <= right) temp[k++] = data[j++];
for (int idx = 0, pos = left; pos <= right; pos++, idx++) {
data[pos] = temp[idx];
}
}
int main() {
int count;
cin >> count;
int value;
while (count--) {
cin >> value;
data.push_back(value);
}
mergeSort(0, data.size() - 1);
for (int num : data) {
cout << num << " ";
}
return 0;
}
- 분할 정복: 최대값과 두 번째 최대값 찾기 배열을 분할하여 부분 배열에서의 최대값과 두 번째 최대값을 구한다.
#include<iostream>
#include<vector>
using namespace std;
int size;
vector<int> data;
int maxValue, secondMax;
void findExtremes(int start, int end) {
if (start == end) {
if (data[start] > maxValue) {
secondMax = maxValue;
maxValue = data[start];
} else {
secondMax = max(secondMax, data[start]);
}
return;
}
int mid = start + (end - start) / 2;
findExtremes(start, mid);
findExtremes(mid + 1, end);
}
int main() {
cin >> size;
int value;
while (size--) {
cin >> value;
data.push_back(value);
}
findExtremes(0, data.size() - 1);
cout << maxValue << " " << secondMax;
return 0;
}
- 완전 탐색: 최대 구간 합 모든 가능한 연속 부분 배열의 합을 계산하여 최대값을 구한다.
#include<iostream>
#include<vector>
using namespace std;
vector<int> data;
int main() {
int count;
cin >> count;
auto calculateMaxSum = [](int n) {
int val;
while (n--) {
cin >> val;
data.push_back(val);
}
int bestSum = 0;
for (int i = 0; i < data.size(); i++) {
for (int j = i; j < data.size(); j++) {
int currentSum = 0;
for (int k = i; k <= j; k++) {
currentSum += data[k];
}
bestSum = max(bestSum, currentSum);
}
}
return bestSum;
};
cout << calculateMaxSum(count);
return 0;
}
- 백트래킹: 미로 탐색 DFS를 활용하여 시작점에서 도착점까지 가능한 경로를 탐색한다.
#include<iostream>
#include<vector>
#include<string>
using namespace std;
const int MAP_SIZE = 8;
string maze[] = {
"OXXXXXXX",
"OOOOOXXX",
"XOXXOOOX",
"XOXXOXXO",
"XOXXXXXX",
"XOXXOOOX",
"XOOOOXOO",
"XXXXXXXO"
};
int startX = 0, startY = 0;
int targetX = 7, targetY = 7;
int dirX[] = {-1, 0, 1, 0};
int dirY[] = {0, 1, 0, -1};
void searchPath(int x, int y) {
if (x == targetX && y == targetY) {
for (int i = 0; i < MAP_SIZE; i++) {
cout << maze[i] << endl;
}
return;
}
for (int d = 0; d < 4; d++) {
int nx = x + dirX[d];
int ny = y + dirY[d];
if (nx >= 0 && nx < MAP_SIZE && ny >= 0 && ny < MAP_SIZE
&& maze[nx][ny] == 'O') {
maze[nx][ny] = ' ';
searchPath(nx, ny);
maze[nx][ny] = 'O';
}
}
}
int main() {
searchPath(startX, startY);
return 0;
}
- 탐욕 알고리즘: 활동 선택 문제 각 활동의 시작 시간과 종료 시간이 주어졌을 때, 겹치지 않는 최대 개수의 활동을 선택한다.
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef pair<int, int> TimePair;
vector<TimePair> activities;
int main() {
int count;
cin >> count;
int start, finish;
while (count--) {
cin >> start >> finish;
activities.push_back({start, finish});
}
sort(activities.begin(), activities.end(),
[](TimePair a, TimePair b) {
return a.second < b.second;
});
vector<bool> selected(activities.size(), false);
int lastEnd = 0;
for (int i = 0; i < activities.size(); i++) {
if (activities[i].first >= lastEnd) {
selected[i] = true;
lastEnd = activities[i].second;
}
}
int resultCount = 0;
for (int i = 0; i < activities.size(); i++) {
if (selected[i]) {
cout << i + 1 << " ";
resultCount++;
}
}
cout << endl << resultCount;
return 0;
}
- 동적 계획법: 최장 공통 부분 수열 (LCS) 두 문자열 사이의 최장 공통 부분 수열의 길이를 동적 계획법으로 구한다.
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string text1, text2;
cin >> text1 >> text2;
int len1 = text1.size();
int len2 = text2.size();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0));
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
cout << dp[len1][len2];
return 0;
}