AcWing算法基础课 Level-2 第二讲 数据结构
生活随笔
收集整理的這篇文章主要介紹了
AcWing算法基础课 Level-2 第二讲 数据结构
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
單鏈表
826. 單鏈表
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10;int idx, l[N], r[N], e[N];//在節(jié)點(diǎn)a的右邊插入x void insert(int a, int x) {e[idx] = x;l[idx] = a, r[idx] = r[a];l[r[a]] = idx, r[a] = idx ++ ; }//刪除節(jié)點(diǎn)a void remove(int a) {r[l[a]] = r[a];l[r[a]] = l[a]; }int main() {//0是左端點(diǎn),1是右端點(diǎn)l[1] = 0, r[0] = 1, idx = 2;int m;cin >> m;while (m -- ){string op;int k, x;cin >> op;if (op == "L"){cin >> x;insert(0, x);}else if (op == "R"){cin >> x;insert(l[1], x);}else if (op == "D"){cin >> k;remove(k + 1);}else if (op == "IL"){cin >> k >> x;insert(l[k + 1], x);}else {cin >> k >> x;insert(k + 1, x);}}for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << " ";return 0; }雙鏈表
827. 雙鏈表
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10;int idx, l[N], r[N], e[N];//在節(jié)點(diǎn)a的右邊插入x void insert(int a, int x) {e[idx] = x;l[idx] = a, r[idx] = r[a];l[r[a]] = idx, r[a] = idx ++ ; }//刪除節(jié)點(diǎn)a void remove(int a) {r[l[a]] = r[a];l[r[a]] = l[a]; }int main() {//0是左端點(diǎn),1是右端點(diǎn)l[1] = 0, r[0] = 1, idx = 2;int m;cin >> m;while (m -- ){string op;int k, x;cin >> op;if (op == "L"){cin >> x;insert(0, x);}else if (op == "R"){cin >> x;insert(l[1], x);}else if (op == "D"){cin >> k;remove(k + 1);}else if (op == "IL"){cin >> k >> x;insert(l[k + 1], x);}else {cin >> k >> x;insert(k + 1, x);}}for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << " ";return 0; }棧
828. 模擬棧
#include <iostream>using namespace std;const int N = 1e5 + 10;int m; int stk[N], tt;int main() {cin >> m;string op;int x;while (m -- ){cin >> op;if (op == "push"){cin >> x;stk[ ++ tt] = x;}else if (op == "pop") -- tt;else if (op == "empty") cout << (tt ? "NO" : "YES") << endl;else cout << stk[tt] << endl;} }3302. 表達(dá)式求值
#include <iostream> #include <stack> #include <unordered_map>using namespace std;stack<int> num; stack<char> op;void eval() {auto b = num.top(); num.pop();auto a = num.top(); num.pop();auto c = op.top(); op.pop();int x;if (c == '+') x = a + b;else if (c == '-') x = a - b;else if (c == '*') x = a * b;else x = a / b;num.push(x); }int main() {unordered_map<char, int> pr{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};string str;cin >> str;for (int i = 0; i < str.size(); i ++ ){char c = str[i];if (isdigit(c)){int x = 0, j = i;while (j < str.size() && isdigit(str[j])) x = x * 10 + str[j ++ ] - '0';i = j - 1;num.push(x);}else if (c == '(') op.push(c);else if (c == ')') // 清空op直到與之對應(yīng)的左括號(hào){while (op.top() != '(') eval();op.pop();}else // 將op中優(yōu)先級(jí)大于等于它的清空,注意左括號(hào){while (op.size() && op.top() != '(' && pr[op.top()] >= pr[c]) eval();op.push(c);}}while (op.size()) eval();cout << num.top() << endl;return 0; }隊(duì)列
829. 模擬隊(duì)列
#include <iostream>using namespace std;const int N = 100010;int m; int q[N], hh, tt = -1;int main() {cin >> m;while (m -- ){string op;int x;cin >> op;if (op == "push"){cin >> x;q[ ++ tt] = x;}else if (op == "pop") hh ++ ;else if (op == "empty") cout << (hh <= tt ? "NO" : "YES") << endl;else cout << q[hh] << endl;}return 0; }單調(diào)棧
830. 單調(diào)棧
- 如果進(jìn)來的那個(gè)?于等于棧頂,說明進(jìn)來的那個(gè)更好(???近),那么棧頂就可以刪掉那么就可以?直刪,直到棧頂?于進(jìn)來的那個(gè)ai,且此時(shí)這個(gè)stk[tt]就是我要找的那個(gè)i的左邊離它最近且?它?的點(diǎn),做完之后再把a(bǔ)i插到隊(duì)列?去
單調(diào)隊(duì)列
154. 滑動(dòng)窗口
KMP
831. KMP字符串
Trie
835. Trie字符串統(tǒng)計(jì)
并查集
836. 合并集合
#include <iostream>using namespace std;const int N = 1e5 + 10;int n, m; int p[N];int find(int x) {if (p[x] != x) p[x] = find(p[x]);return p[x]; }int main() {cin >> n >> m;for (int i = 1; i <= n; i ++ ) p[i] = i; // 并查集初始化while (m -- ){char op[2];int a, b;scanf("%s%d%d", op, &a, &b);if (*op == 'M') p[find(a)] = find(b);else{if (find(a) == find(b)) puts("Yes");else puts("No");}} }837. 連通塊中點(diǎn)的數(shù)量
#include <iostream>using namespace std;const int N = 1e5 + 10;int n, m; int fa[N], cnt[N];int find(int x) {if (fa[x] != x) fa[x] = find(fa[x]);return fa[x]; }int main() {cin >> n >> m;for (int i = 1; i <= n; i ++ ) fa[i] = i, cnt[i] = 1;while (m -- ){string op;int a, b;cin >> op;if (op == "C"){cin >> a >> b;a = find(a), b = find(b);if (a != b){fa[a] = b;cnt[b] += cnt[a];}}else if (op == "Q1"){cin >> a >> b;if (find(a) == find(b)) puts("Yes");else puts("No");}else{cin >> a;cout << cnt[find(a)] << endl;}} }堆
838. 堆排序
- 二叉堆是一種滿足堆性質(zhì)的完全二叉樹,因此有父節(jié)點(diǎn)與兩個(gè)兒子下標(biāo)之間的關(guān)聯(lián)
- 任意一個(gè)結(jié)點(diǎn)權(quán)值都小于等于其父親的權(quán)值
- 堆排序,所以是先把所有數(shù)輸進(jìn)來再進(jìn)行排序
- 分析i=n/2,進(jìn)行down操作時(shí)必須滿足左右兒子已經(jīng)是個(gè)堆
- 分析i=n/2,不能從根結(jié)點(diǎn)開始down,要找到一個(gè)點(diǎn)滿足以下三個(gè)性質(zhì)(1.左右兒子滿足堆的性質(zhì);2.下標(biāo)最大(因?yàn)橐媳闅v);3.不是葉結(jié)點(diǎn)(葉結(jié)點(diǎn)一定滿足堆的性質(zhì)))。而n/2是最后一個(gè)結(jié)點(diǎn)的父節(jié)點(diǎn)
- 注意這里要先有一個(gè)cnt去copy n的值,因?yàn)樵趍次pop后元素個(gè)數(shù)已經(jīng)不是n了
- down :先找出左右兒子和父節(jié)點(diǎn)三者中最大的,如果最大的不是父節(jié)點(diǎn),那么就將父節(jié)點(diǎn)與兒子交換,并且以兒子為父節(jié)點(diǎn)遞歸
- 輸出堆頂操作 :先輸出堆頂,將堆頂用最后元素替換,并將長度-1,并對1號(hào)使用down
839. 模擬堆
- 首先要理解的是hp和ph數(shù)組存的是什么;hp是heap pointer的縮寫,表示堆數(shù)組下標(biāo)到第k個(gè)插入的映射,而ph和hp數(shù)組是互為反函數(shù)的
- 那么為什么要用到這兩個(gè)數(shù)組呢 ?原因是在刪除第k個(gè)插入元素的操作時(shí),首先得知道第k個(gè)插入元素在堆數(shù)組中的下標(biāo)。因此用ph數(shù)組就能知道第k個(gè)插入元素在堆數(shù)組中的下標(biāo),然后再在第k個(gè)元素所在的位置進(jìn)行down和up操作
- 在swap操作中我們輸入的是堆數(shù)組的下標(biāo),無法知道堆數(shù)組下標(biāo)對應(yīng)的是第幾個(gè)插入的元素,所以需要hp數(shù)組,
哈希表
840. 模擬散列表
- 拉鏈法 :
- 做哈希時(shí),數(shù)組?度,也就是模的這個(gè)數(shù)(上圖1e5),?般要取成?個(gè)質(zhì)數(shù),且要離2的整次冪盡可能遠(yuǎn)。在這種情況下,沖突的概率是最?的。
- 拉鏈法,要用到vector
- insert函數(shù)中,?先要想哈希函數(shù),要把x映射到0到N之間的?個(gè)數(shù);x % N 在C++中如果x是負(fù)數(shù)的話余數(shù)是負(fù)數(shù),所以再加?個(gè)N就?定可以變成正的余數(shù),再模N。得到的k就是我們的哈希值
- 開放尋址法 :
- find函數(shù)就是找x所在位置或者如果不存在則返回它應(yīng)該存儲(chǔ)的位置(也就是在第一次找到的k后第一個(gè)為空的位置)。如果循環(huán)內(nèi)找到了上屆,變回0。就是有“找不找得到呢?”的奇妙。
841. 字符串哈希
- p[i]存的是p的i次方,h[i]是字符串前綴哈希值。在讀入詢問前先做預(yù)處理
- 下標(biāo)從1開始
總結(jié)
以上是生活随笔為你收集整理的AcWing算法基础课 Level-2 第二讲 数据结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑马程序员pink老师前端入门教程,零基
- 下一篇: 软件设计师考试上午真题 考前速记