algo[2]

建北電資小社課

2023/10/27

  • 225班
  • 電子計算機研習社_學術長
  • 綽號807
  • 資讀講師

這我

複雜度

Complexity

  • 評估用量
  • 時間複雜度
  • 空間複雜度

複雜度

飯粒

n
T

給   個整數(陣列a)

求這   個數的和

n
n
n
int sum=0;
for(int i=0;i<n;i++) sum+=a[i];
cout<<sum<<"\n";
O(n)

複雜度: 

符號

\Theta
O
o
\Omega
\omega

上界==下界

上界 最大值(包含)

上界 最大值(不含)

下界 最小值(包含)

下界 最小值(不含)

飯粒

n
T
O(n)

給   個整數(陣列a)

求這   個數的和

n
n
n
int sum=0;
for(int i=0;i<n;i++) sum+=a[i];
cout<<sum<<"\n";

複雜度: 

\Theta(n)
\Omega(n)

你可能會想問

乘法比加法慢,那複雜度是否相同?

  • 由於兩者的計算時間都是常數,所以可記為
  • 做n次加法和做n次乘法都是
O(n)
O(1)
O(c_1)
O(c_2)
O(1)
O(c_1 \times n)
O(c_2 \times n)
O(n)

你可能會想問

宣告sum 輸出sum 都需要時間,那這些時間需不需要算進去?

  • 宣告sum 輸出sum 遠小於 計算
  • 複雜度 取 成長性最快者

成長性

O(1)
O(log(n))
O(n)
O(n \times log(n))
O(n^2)
O(n!)
O(2^n)
O(n^3)
O(n^2 \times log(n))
O(n \times log^2(n))

成長性

O(log(n))
O(n)
O(n^2)
O(n!)
O(2^n)
O(n\times log(n))

時間限制: 1000 ms

記憶體量: 65536 MB 

電腦每秒約      次運算

常見題目限制

10^9

複雜度範圍

複雜度 \times 常數 \le 10^9 \\ \because 常數不大 \\ \therefore 複雜度 \le 10^8

實際情況須依長數而定

時間複雜度範圍

實際情況須依長數而定

O(1)
O(log(n))
O(n)
O(n \times log(n))
O(n^2)
O(n!)
O(2^n)
\infty
10^{20}
10^8
10^7
10^4
28
12

空間複雜度範圍

  • 題目限制較不一

資料型態 (複習)

資料型態 用途 記憶體大小
int 整數-2³¹~2³¹-1(約2*10⁹~-2*10⁹) 4 bytes
long long 更大的整數 -2⁶³~2⁶³-1(約9*10¹⁸~-9*10¹⁸) 8 bytes
float 浮點數 (可以有小數點的數字) 4 bytes
double 更精確浮點數 (可以有小數點的數字) 8bytes
char 字元 1 byte
string 字串 可變

記憶體/檔案單位

1 = 8 bits \\ 1 KB = 1000 bytes \\ 1 KiB = 1024 bytes \\ 1 MB = 10^6 bytes \\ 1 Mib = 2^{20} bytes \approx 10^6 \\ 1 GB = 10^9 bytes \\ 1 GiB = 2^{30} bytes \approx 10^9 \\ 1 TB = 10^{12} bytes \\ 1 TiB = 2^{40} bytes \approx 10^{12} \\
  • 評估演算法速度、記憶體用量
  • 找出適當演算法、資料結構

為什麼要學

STL能吃嗎?

  • 寫好的資料結構
  • 寫好的迭代器

標準樣板函式庫

Standard Template Library

好ㄟ

都幫我寫好了

那我要幹嘛

pair

  • pair
  • 前: first
  • 後: second

宣告

pair<int,int> p;
first(int) second(int)

取值 

cin>>p.first;
cin>>p.second;
first second

vector

  • 不是向量
  • 長度可變的陣列

vector

這東西顯然推爆吧

宣告

陣列

vector

int arr[5]={0};
vector<int> arr(5,0);
int arr[5];
vector<int> arr(5);
vector<int> arr;

輸出 arr 的大小 5

.size()

vector<int> arr(5,7);
cout<<arr.size()<<"\n";

arr 為空 輸出 1

.empty()

vector<int> arr;
cout<<arr.empty()<<"\n";

.push_back(要插入的)

[]

vector<int> arr;
arr.push_back(8);
arr.push_back(0);
arr.push_back(7);

[8]

[8,0]

[8,0,7]

[]

.pop_back()

arr.pop_back();
arr.pop_back();
arr.pop_back();

[8]

[8,0]

[8,0,7]

  1. 自動開兩倍長的陣列
  2. 將現有自動的複製過去
  3. 好ㄟ 容量夠了

push_back 容量不足

O(2n)
O(n)

複雜度:

.reserve()

  • 為push_back預留容量

[]

cout<<arr.capacity()<<"\n";

[8,,]

[8,0,]

[8,0,7]

[,,]

.capacity()

  • 取得容量空間大小
cout<<arr.capacity()<<"\n";

.swap(vector)

  • 重置

[]

vector<int>().swap(arr);
cout<<arr.empty()<<"\n";

[8,0,7]

arr: 

題單

太多了不想放ㄟ

iterator

敬請見諒😆

迭代

  • 迭代器
  • 寫好的~ 讓你便利遍歷
  • 有些資料結構過於複雜

iterator

iterator

遍歷

#include<bits/stdc++.h>
using namespace std;
int main(){
    vector<int> arr(5);

    for(vector<int>::iterator it=arr.begin();it!=arr.end();it++){
        cin>>*it;
    }
    for(vector<int>::reverse_iterator it=arr.rbegin();it!=arr.rend();it++){
        cout<<*it<<" ";
    }
    cout<<"\n";
}

便利遍歷

#include<bits/stdc++.h>
using namespace std;
int main(){
    vector<int> arr(5);

    for(auto it=arr.begin();it!=arr.end();it++){
        cin>>*it;
    }
    for(auto it=arr.rbegin();it!=arr.rend();it++){
        cout<<*it<<" ";
    }
    cout<<"\n";
}

變例便利遍歷

#include<bits/stdc++.h>
using namespace std;
int main(){
    vector<int> arr(5);
	
    for(int &i:arr){
        cin>>i;
    }
    for(auto &i:arr){
        cout<<i<<" ";
    }
    cout<<"\n";
}

題單

 

stack

  • 放最上層
  • 拿最上層
  • Last-In First-Out

stack

  • LIFO

.push()

  • 放入最上層
stack<int> stk;
stk.push(20);
stk.push(10);

10

top()

top()

20

stk

宣告

.top()

  • 最上層
  • stack為空時,Segment Default
stk.top()+=2
cout<<stk.top()<<endl;

10

top()

20

stk

12

12

  • 取得stack大小

.size()

5

stk

  • 取得stack大小

.size()

5

stk

stk 為空 輸出 1

.empty()

stack<int> stk;
cout<<stk.empty()<<"\n";

queue

  • 佇列
  • 排隊顯然要先來先走吧!!!👀
  • First-In First-Out

queue

  • FIFO
\lt
\lt
\lt
\lt
\lt
\lt

宣告

queue<int> q;

q

.push()

q.push(8);
q.push(0);
q.push(7);

q

8

0

7

back

back

back

front

.front() .back()

q.front()--;
q.back()++;
cout<<q.front()<<","<<q.back()<<"\n";

q

8

0

7

back

front

7

8

7,8

.pop()

q.pop();
q.pop();
q.pop();

q

7

0

8

back

front

front

front

.size() .empty

cout<<q.size()<<"\n";
cout<<q.empty()<<"\n";

q

0

1

priority_queue

  • 優先權佇列
  • 優先者先出
  • 預設大的在前

priority_queue

宣告

#include<bits/stdc++.h>
using namespace std;
int main(){
    priority_queue<int,vector<int>,decltype([](int a,int b){return a<b;})> pq;
    pq.push(5);
    pq.push(7);
    cout<<pq.top()<<endl;
}

不想用struct 那就用lambda

宣告

priority_queue<int> pq;
  • 存int
  • 有大到小

宣告

priority_queue<int,vector<int>,greater<int>> pq;

想由小到大

宣告

#include<bits/stdc++.h>
using namespace std;
struct comp{
    bool operator()(int a,int b){
        return a<b;
    }
};
int main(){
    priority_queue<int,vector<int>,comp> pq;
}

想自訂比較函示

這是有小到大有夠不值覺得啦啦啦~~~

宣告

  • 蛤 什麼是 decltype
  • 欸 我也不知道ㄟ

.push()

pq.push(0);
pq.push(8);
pq.push(7);

8

pq

7

0

.top()

pq.top()

8

pq

7

0

.pop()

pq.push(8);
pq.push(0);
pq.push(7);

8

pq

7

0

.size() .empty

cout<<pq.size()<<"\n";
cout<<pq.empty()<<"\n";

0

1

複雜度 整理

top()
push()
pop()
O(1)
O(log(n))
O(log(n))

list

  • 存自己
  • 下一位
  • 上一位

鄰接串列

  • STL的太難用了
  • 我們自己寫吧

最後最後

  • @cjtsai蠻推的我亂寫的不要打我

今天蠻多例題都是資訊枝芽

演算法小社[2]

By 建中店自計算機研習社學術長807⁸⁰⁷