개요: 정렬 알고리즘
데이터들을 특정 기준에 따라서 순서대로 나열한다.
선택 정렬
데이터들 중 가장 작은 데이터를 '선택'해서 맨앞의 데이터와 바꾼다.
N번만큼 가장 작은 수를 찾아서 맨앞으로 보내므로 N + N-1 + N-2 + ... 시간 복잡도는 O(N2)이다.
특정 리스트에서 가장 작은 데이터를 찾는 일이 코딩 테스트에서 잦으므로 선택 정렬 소스 코드를 자주 작성해 볼 것을 권장한다.
#include <iostream>
using namespace std;
int n = 10;
int target[10] = { 7,5,8,0,3,1,6,2,4,8 };
int main() {
for (int i = 0; i < n; i++) {
int min_index = i;
for (int j = i + 1; j < n; j++) {
if (target[min_index] > target[j]) {
min_index = j;
}
}
swap(target[i], target[min_index]);
}
}
삽입 정렬
처리되지 않은 특정한 데이터를 한 개씩 골라서 적절한 위치(삽입될 데이터보다 작은 데이터를 만나면 그 위치에서 멈춘다)에 삽입한다.
첫 번째는 정렬되어 있다고 가정, 두 번째 원소부터 어떤 위치에 삽입할 것인지 판단한다.
시간 복잡도는 O(N^2)이지만, 최선의 경우 O(N)이다.
#include <iostream>
using namespace std;
int n = 10;
int target[10] = { 7,5,8,0,3,1,6,2,4,8 };
int main() {
for (int i = 1; i < n; i++) {
for (int j = i; j > 0; j--) {
if (target[j] < target[j - 1]) {
swap(target[j], target[j - 1]);
}
else
break;
}
}
}
퀵 정렬
기준 데이터 피벗을 설정하고 그 기준 데이터보다 작은 데이터와 큰 데이터의 위치를 바꾼다.
가장 기본적인 퀵 정렬은 첫 번째 원소를 기준 데이터 피벗으로 설정한다.
평균 시간 복잡도는 O(NlogN), 최악의 경우 O(N^2)이다. (너비*높이 = N * logN = NlogN)
#include <iostream>
using namespace std;
int n = 10;
int target[10] = { 7,5,8,0,3,1,6,2,4,8 };
void quick_sort(int* target, int start, int end) {
if (start >= end)
return;
int pivot = start;
int left = start + 1;
int right = end;
while (left <= right) {
while (left <= end && target[left] <= target[pivot]) {
left++;
}
while (right > start && target[right] >= target[pivot]) {
right--;
}
if (left > right)
swap(target[pivot], target[right]);
else
swap(target[left], target[right]);
}
quick_sort(target, start, right - 1);
quick_sort(target, right + 1, end);
}
int main() {
quick_sort(target, 0, n - 1);
}
계수 정렬
데이터 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때 매우 빠르게 동작하는 정렬 알고리즘.
데이터의 개수가 N, 양수 데이터 중 최댓값이 K일 때 최악의 경우에도 O(N + K)를 보장한다.
때에 따라서 심각한 비효율성을 초래할 수 있다.
#include <iostream>
using namespace std;
#define MAX_VALUE 9
int n = 15;
int arr[15] = { 7,5,9,0,3,1,6,2,9,1,4,8,0,5,2 };
int cnt[MAX_VALUE + 1];
int main() {
for (int i = 0; i < n; i++) {
cnt[arr[i]] += 1;
}
for (int i = 0; i <= MAX_VALUE; i++) {
for (int j = 0; j < cnt[i]; j++) {
cout << i << ' ';
}
}
}
문제 6-4. 두 배열의 원소 교체
설명
동빈이는 두 개의 배열 A와 B를 가지고 있다. 두 배열은 N개의 원소로 구성되어 있으며, 배열의 원소는 모두 자연수이다. 동빈이는 최대 K 번의 바꿔치기 연산을 수행할 수 있는데, 바꿔치기 연산이란 배열 A에 있는 원소 하나와 배열 B에 있는 원소 하나를 골라서 두 원소를 서로 바꾸는 것을 말한다. 동빈이의 최종 목표는 배열 A의 모든 원소의 합이 최대가 되도록 하는 것이며, 여러분은 동빈이를 도와야한다.
N, K, 그리고 배열 A와 B의 정보가 주어졌을 때, 최대 K 번의 바꿔치기 연산을 수행하여 만들 수 있는 배열 A의 모든 원소의 합의 최댓값을 출력하는 프로그램을 작성하라.
예를 들어 N = 5, K = 3이고, 배열 A와 B가 다음과 같다고 해보자.
배열 A = [1, 2, 5, 4, 3]
배열 B = [5, 5, 6, 6, 5]
이 경우, 다음과 같이 세 번의 연산을 수행할 수 있다.
연산 1) 배열 A의 원소 '1'과 배열 B의 원소 '6'을 바꾸기
연산 2) 배열 A의 원소 '2'와 배열 B의 원소 '6'을 바꾸기
연산 3) 배열 A의 원소 '3'과 배열 B의 원소 '5'를 바꾸기
세 번의 연산 이후 배열 A와 배열 B의 상태는 다음과 같이 구성될 것이다.
배열 A = [6, 6, 5, 4, 5]
배열 B = [3, 5, 1, 2, 5]
이때 배열 A의 모든 원소의 합은 26이 되며, 이보다 더 합을 크게 만들 수는 없다.
입력
- 첫 번째 줄: N, K 가 공백으로 구분되어 입력 (1 <= N <= 100,000, 0 <= K <= N)
- 두 번째 줄: 배열 A의 원소들이 공백으로 구분되어 입력 (원소 a < 10,000,000인 자연수)
- 세 번째 줄: 배열 B의 원소들이 공백으로 구분되어 입력 (원소 b < 10,000,000인 자연수)
출력
- 최대 K번 바꿔치기 연산을 수행해서 가장 최대의 합을 갖는 A의 모든 원소 값의 합을 출력
입력 예시
5 3
1 2 5 4 3
5 5 6 6 5
출력 예시
26
아이디어
매번 배열 A에서의 작은 원소를 골라서 배열 B의 큰 원소와 바꾼다.
A는 오름차순, B는 내림차순으로 정렬한다.
두 배열의 원소를 첫 번째 인덱스부터 확인하면서 A 원소가 B 원소보다 작을 때만 교체를 진행한다.
두 배열의 원소가 최대 100,000개까지 입력될 수 있으므로 최악의 경우 O(NlogN)을 보장하는 알고리즘인 퀵 정렬을 사용해야 한다.
내 코드
// 6-4. 두 배열의 원소 교체
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n, k;
vector<int> v_a;
vector<int> v_b;
void change() {
// ** 작은 원소나 큰 원소를 알아낼 때 sorting!!
sort(v_a.begin(), v_a.end());
sort(v_b.begin(), v_b.end(), greater<>());
for (int i = 0; i < k; i++) {
if(v_a[i] < v_b[i]) // ** 테케 틀렸을 것임
swap(v_a[i], v_b[i]);
}
}
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++) {
int value;
cin >> value;
v_a.push_back(value);
}
for (int i = 0; i < n; i++) {
int value;
cin >> value;
v_b.push_back(value);
}
change();
int result = 0;
for (int i = 0; i < n; i++) {
result += v_a[i];
}
cout << result << "\n";
}
'알고리즘 > 이것이 코딩 테스트다' 카테고리의 다른 글
08: 다이나믹 프로그래밍 (0) | 2022.03.27 |
---|---|
07: 이진 탐색 (0) | 2022.03.25 |
05: DFS, BFS (0) | 2022.03.14 |
04: 구현 (0) | 2022.03.13 |
03: Greedy 알고리즘 (0) | 2022.03.08 |