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