Ethan Yeh
INFOR 38th — 學術
INFOR38 學術 葉倚誠
| # 1 | 標準模板庫 (STL) |
| # 2 | 複雜度 |
| # 2 | 容器 Container/適配器 Adapter |
| # 3 | Pair |
| # 4 | 迭代器 iterator |
| # 5 | 演算法 Algorithms |
| # 7 | 題 |
時間複雜度和空間複雜度是衡量一個演算法效率的重要標準
OI Wiki
透過複雜度可以判定一個演算法的執行效率
E.g. 加減乘除、變數存取等皆為基本操作
算法用時隨數據規模而增長的趨勢,即為時間複雜度
#include <bits/stdc++.h>
using namespace std;
int main() {
int n = 100000;
for (int i = 0; i < n; ++i) {
cout << "hello world\n";
}
return 0;
}
如果 n 不被看作輸入規模,那麼這段程式的時間複雜度就是 𝑂(1)
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < m; ++k) {
cout << "hello world\n";
}
}
}
}
容器:用來儲存資料的結構
順序容器:array、vector、list、deque
關聯容器:set、map
無序容器:unorderd_set、unorderd_map
適配器:類似容器,但沒有迭代器
queue、priority_queue、stack
Vector
Deque
List
Array
#include <array>
array<int, 5> a = {1, 2, 3, 4, 5};
| operator[] / at() | 存取指定索引值元素 |
| front() / back() | 存取第一個/最後一個元素 |
| fill() | 填充指定元素在容器中 |
| empty() | 回傳容器是否為空 |
| size() | 回傳容器長度 |
#include <vector>
vector<int> v = {1, 2, 3, 4, 5}
| operator[] / at() | 存取指定索引值元素 |
| front() / back() | 存取第一個/最後一個元素 |
| push_back() / pop_back() | 在容器末端插入/刪除元素 |
| clear() | 清空容器 |
| empty() | 回傳容器是否為空 |
| size() | 回傳容器長度 |
| resize() | 改變容器長度 |
#include <deque>
deque<int> d = {1, 2, 3, 4, 5}
| operator[] / at() | 存取指定索引值元素 |
| front() / back() | 存取第一個/最後一個元素 |
| push_back() / pop_back() | 在容器末端插入/刪除元素 |
| push_front() / pop_front() | 在容器頭端插入/刪除元素 |
| clear() | 清空容器 |
| empty() | 回傳容器是否為空 |
| size() | 回傳容器長度 |
| resize() | 改變容器長度 |
#include <list>
list<int> l = {1, 2, 3, 4, 5}
| empty() | 回傳容器是否為空 |
| size() | 回傳容器長度 |
| resize() | 改變容器長度 |
Map
Set
multiset
multimap
#include <set>
set<T> s;
insert(it, x) / erase(x / it)
find(x) / count(x)
size()
empty() / clear()
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
set<int> s;
for (int i = 0; i < 10; ++i) s.insert(i);
for (int i = 0; i < 10; ++i) s.insert(i);
for (auto it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
} // 0 1 ... 9
cout << endl;
cout << s.size() << endl; // 10
cout << s.count(5) << endl; // 1
return 0;
}
#include <bits/std.c++.h>
using namespace std;
int main() {
set<int> s;
int color;
for (int i = 0; i < 4; i++) {
cin >> color;
s.insert(color);
}
cout << 4 - s.size() << endl;
return 0;
}#include <map>
map<T, T> m;
insert({key, val}) / erase(key / it)
find(key) / count(key)
size()
empty() / clear()
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
map<string, int> m;
m["a"] = 1;
m["b"] = 2;
m["c"] = 3;
m.insert({"d", 4});
cout << m.count("a") << endl; // 1
cout << (m.find("a") != m.end()) << endl; // 1
return 0;
}
#include <bits/std.c++.h>
using namespace std;
int main() {
int n; cin >> n;
map<int, int> counts;
int max_freq = 0;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
counts[a]++;
max_freq = max(max_freq, counts[a]);
}
cout << max_freq << endl;
return 0;
}Stack
priority_queue
Queue
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
queue<int> q;
for (int i = 1; i <= 5; ++i) q.push(i);
while (!q.empty()) { // 1 2 3 4 5
cout << q.front() << " ";
q.pop();
}
cout << endl;
return 0;
}
#include <queue>
queue<T> q;
push(x) / pop()
front() / back()
size() / empty()
Deque 為底層容器
先進先出
#include <priority_queue>
priority_queue<T, Container, Compare> pq
push(x) / pop()
top()
size() / empty()
自訂底層容器
自訂比較函數
按照優先級排序
#include <bits/stdc++h>
using namespace std;
int main() {
vector<int> data = {10, 2, 45, 18, 7};
priority_queue<int, vector<int>, less<int>> pq;
for (int num : data) {
pq.push(num);
}
while (!pq.empty()) {
cout << pq.top() << " ";
pq.pop();
}
return 0;
}#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
stack<int> s;
for (int i = 0; i < 10; i++) s.push(i);
while (!s.empty()) { // 9 8 7 6 5 4 3 2 1 0
cout << s.top() << " ";
s.pop();
}
cout << endl;
return 0;
}
#include <stack>
stack<T> s;
push(x) / pop()
top()
size() / empty()
Deque 為底層容器
後進先出
pait<int, double> = make_pair(1, 2.0)#include <bits/stdc++.h>
using namespace std;
int main() {
pair<int, double> p1;
p1.first = 1;
p1.second = 2.0;
pair<int, double> p2 = make_pair(1, 2.0);
auto p3 = make_pair(1, 2.0);
return 0;
}
| 單向迭代器 ForwardIterator | 僅能向前遍歷容器 |
| 雙向迭代器 BidirectionalIterator | 可以向前 / 後遍歷容器 |
| 隨機存取迭代器 RandomAccessIterator | 可以任意訪問整個容器 |
● 單向迭代器:
unorded_set, unorded_multiset, unorded_map, unorded_multiset
● 雙向迭代器:
list, set, multiset, map, multimap
● 隨機存取迭代器
array、vector、deque
● 無迭代器 (非容器)
queue、priority_queue、stack、pair
| iterator data.begin() | 回傳開頭 iterator |
| iterator data.end() | 回傳結尾 iterator |
| iterator next(iterator it) | 回傳下一個 iterator |
| terator prev(iterator it) | 回傳上一個 iterator |
| *it | 存取 iterator |
| it -> func(); | (*it).func(); |
| it + 3 | 回傳後 3 個 iterator |
STL 內建的一些函數
方便執行常用的操作
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> v(n);
for (int i=0;i<n;i++) {
cin >> v[i];
}
sort(v.begin(),v.end());
for (int i=0;i<n;i++) {
cout << v[i] << ' ';
}
}
#include <bits/stdc++.h>
using namespace std;
bool cmp(int a ,int b) {
return a < b; // 原本從小到大,變成從大到小
}
int main() {
int n;
cin >> n;
vector<int> v(n);
for (int i=0;i<n;i++) {
cin >> v[i];
}
sort(v.begin(), v.end(), cmp);
for (int i=0;i<n;i++) {
cout << v[i] << ' ';
}
}
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
vector<int> v = {5, 1, 3, 4, 2};
for (int i : v) cout << i << " ";
cout << endl;
// 5 1 3 4 2
reverse(v.begin(), v.end());
for (int i : v) cout << i << " ";
cout << endl;
// 2 4 3 1 5
return 0;
}
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
vector<int> v = {1, 1, 2, 3, 3, 4, 6, 7, 7, 7};
cout << count(v.begin(), v.end(), 7) << endl; // 3
cout << count(v.begin(), v.end(), 1) << endl; // 2
cout << count(v.begin(), v.end(), 8) << endl; // 0
return 0;
}
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
cout << min(10, 5) << endl; // 5
cout << max(10, 5) << endl; // 10
cout << min({10, 5, 20}) << endl; // 5
cout << max({10, 5, 20}) << endl; // 20
return 0;
}
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
if (find(v.begin(), v.end(), 3) != v.end()) cout << "Yes" << endl;
else cout << "No" << endl; // Yes
if (find(v.begin(), v.end(), 6) != v.end()) cout << "Yes" << endl;
else cout << "No" << endl; // No
return 0;
}
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
v.erase(remove(v.begin(), v.end(), 3), v.end());
for (const auto &i : v) cout << i << " ";
cout << endl;
// 1 2 4 5
return 0;
}#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int f(const int &x) { return x * 2; }
int main() {
vector<int> v = {1, 2, 3, 4, 5};
string s = "HeLlo woLRD";
transform(v.begin(), v.end(), v.begin(), f);
for (const auto &i : v) cout << i << " ";
cout << endl;
// 2 4 6 8 10
transform(s.begin(), s.end(), s.begin(), ::tolower);
cout << s << endl;
// hello world
return 0;
}
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
void solve() {
int n;
if (!(cin >> n)) return;
vector<int> target(n);
for (int i = 0; i < n; i++) {
cin >> target[i];
}
stack<int> s;
int next_push = 1;
bool possible = true;
for (int i = 0; i < n; i++) {
while ((s.empty() || s.top() != target[i]) && next_push <= n) {
s.push(next_push);
next_push++;
}
if (!s.empty() && s.top() == target[i]) {
s.pop();
} else {
possible = false;
break;
}
}
if (possible) cout << "Yes" << endl;
else cout << "No" << endl;
}
int main() {
int t;
if (cin >> t) {
while (t--) {
solve();
}
}
return 0;
}By Ethan Yeh