알고리즘 강의를 들은 내용들을 기억하기 위해 전반적인 내용을 정리하였습니다.
https://velog.io/@khg04202/STL-%EC%B4%9D%EC%A0%95%EB%A6%AC
시간 복잡도 요구 사항 파악
map / set 또는 unordered_map / unordered_setunordered_map / unordered_setpriority_queuequeuedeque정렬의 필요성
map, set, 혹은 sort 함수 사용lower_bound, upper_boundnth_element중복 제거 & 효율적 관리
unique + erase 패턴 (정렬 필요)set / unordered_setO(Log N), 가장 우선순위 높은 원소 조회는 O(1) (top())#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() {
priority_queue<int> pq;
pq.push(6);
pq.push(12);
pq.push(4);
cout << "top: " << pq.top() << endl; // 12
pq.pop(); // top(12) 제거
cout << "top: " << pq.top() << endl; // 6
}
최소 힙은 선언 할 때 3번째 인자로 greater<T>
priority_queue<int, vector<int>, greater<int>> minPq;
next_permutation / prev_permutation
사전 순 다음 순열 / 사전 순 이전 순열
반드시 원본 데이터를 정렬한 뒤 사용
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
for(int x : v) cout << x << " "; // 1 2 3 4 5
cout << endl;
// 다음 순열
next_permutation(v.begin(), v.end());
for(int x : v) cout << x << " "; // 1 2 3 5 4
cout << endl;
// 다음 순열
next_permutation(v.begin(), v.end());
for(int x : v) cout << x << " "; // 1 3 2 4 5
cout << endl;
// 이전 순열
prev_permutation(v.begin(), v.end());
for(int x : v) cout << x << " "; // 1 2 3 5 4
cout << endl;
}
<Numeric> 헤더#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
vector<int> psum(4);
partial_sum(v.begin(), v.end(), psum.begin());
cout << psum[0] << endl; // 1
cout << psum[1] << endl; // 3 (1 + 2)
cout << psum[2] << endl; // 6 (1 + 2 + 3)
cout << psum[3] << endl; // 10 (1 + 2 + 3 + 4)
int sum = psum[3] - psum[1]; // 구간 [2, 4]의 합
}
정렬 필수
vector<int> v = {1, 4, 4, 2, 2, 2, 5, 1};
sort(v.begin(), v.end()); // 정렬 필수! 1, 1, 2, 2, 2, 4, 4, 5
auto newEnd = unique(v.begin(), v.end()); // 1, 2, 4, 5, ?, ?, ?, ?
v.erase(newEnd, v.end()); // 1, 2, 4, 5
// 총합 구하기 3번 째 인자: 초기 값
int sum = accumulate(v.begin(), v.end(), 0);
// 4번째 인자로 multiplies<int>())를 넣어 총 곱 계산, 초기 값 1로 해야함
int product = accumulate(v.begin(), v.end(), 1, multiplies<int>());
lower_bound / upper_bound 정렬된 구간에서 이진 탐색 O(log n)
lower_bound : x 이상의 값이 나오는 최초 위치
upper_bound : x 초과의 값이 나오는 최초 위치
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 4, 4, 5, 7, 8};
auto lb = lower_bound(v.begin(), v.end(), 4);
auto ub = upper_bound(v.begin(), v.end(), 4);
cout << (lb - v.begin()) << endl; // 2
cout << (ub - v.begin()) << endl; // 4
}
구간 내 원소를 함수를 모두 적용하는 함수
2가지 사용법
1. 단항 연산: 각 원소를 하나씩 변환 (예: 모두 2배)
2. 이항 연산: 두 구간의 원소들을 짝지어서 변환 (예: 같은 인덱스끼리 더하기)
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath> // pow 함수를 위해 필요
using namespace std;
int main() {
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2(5); // v2 크기 미리 확보!
transform(v1.begin(), v1.end(), v2.begin(), [](int x){
return pow(x, 2); // 각 원소를 제곱!
});
for(int x : v2) cout << x << " "; // 1 4 9 16 25
}
v2 확보 필수!
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric> // plus<int> 를 위해 필요
using namespace std;
int main() {
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {6, 7, 8, 9, 10};
vector<int> v3(5);
transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), plus<int>()); // plus<int>() 사용!
for(int x : v3) cout << x << " "; // 7 9 11 13 15
}
v1, v2는 반드시 같은 크기
max_element, min_element, minmax_element
iterator 반환
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {4, 1, 6, 3, 8, 2};
// 1. max_element: 최댓값의 위치를 찾아줍니다
auto max_it = max_element(v.begin(), v.end());
cout << "최댓값: " << *max_it << endl; // 8 출력
// 2. min_element: 최솟값의 위치를 찾아줍니다
auto min_it = min_element(v.begin(), v.end());
cout << "최솟값: " << *min_it << endl; // 1 출력
// 3. minmax_element: 최솟값과 최댓값을 한 번에! (구조적 바인딩 활용했어요)
auto [min_iter, max_iter] = minmax_element(v.begin(), v.end());
cout << "최댓값2: " << *max_iter << endl; // 8 출력
cout << "최소값2: " << *min_iter << endl; // 1 출력
}
count, count_if
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {1, 1, 2, 2, 3, 3};
// 값이 2인 원소 개수
int cnt = count(v.begin(), v.end(), 2);
// 짝수 개수
int even_cnt = count_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; });
cout << "값이 2인 원소 개수: " << cnt << endl;
cout << "짝수인 원소 개수: " << even_cnt << endl;
}
std::distance, std::advance
iterator 거리 계산 및 이동
int idx = distance(v.begin(), it); // idx = 2
advance(it, idx); // it를 2칸 전진
#include <bits/stdc++.h>
C++ 표준 라이브러리를 모두 포함
ios::sync_with_stdio(false);cin.tie(nullptr); (or cin.tie(0);)#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int a, b;
cin >> a >> b;
cout << a + b << "\n";
}
\n을 쓰는 이유: endl을 쓰게 되면 출력 버퍼가 강제로 flush 되어 느려질 수 있어서 \n 사용
getline(cin, s);
가능한 모든 경우의 수 시도
자료의 크기가 작거나, 최적화된 알고리즘을 떠올리기가 어려울 때, 혹은 검증 과정을 위해서(정답이 정말 맞는지) 사용
n개의 원소가 있다면 부분집합의 개수는 2^n, 순열의 개수는 n! (팩토리얼) 가 됩니다.
불필요한 중복을 제거하여 최적화 가능