acwing算法基础课II
2022/2/8 1:12:33
本文主要是介绍acwing算法基础课II,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
acwing基础课 II 数据结构
链表
数组模拟单链表
单链表 格式就是这样吧 e[N]
代表当前点 ne[N]
代表下一代的点. 插入也很简洁.
int ne[N6], idx = 1, e[N6]; void insert(int x, int y) { ne[idx] = ne[x]; ne[x] = idx; e[idx++] = y; } void insert_head(int x) { insert(0, x); } void delete_node(int x) { ne[x] = ne[ne[x]]; } int main() { int m = read(); ne[0] = -1; char s; while (m--) { cin >> s; int x = read(), y; if (s == 'H') insert_head(x); else if (s == 'I') y = read(), insert(x, y); else if (s == 'D') delete_node(x); } for (int i = ne[0]; i != -1; i = ne[i]) { O(e[i]); } }
数组模拟双链表 ★★★
int idx = 2, e[N5], l[N5], r[N5]; void init() { l[1] = 0, r[0] = 1; //这个l0 和 r1真能用到么 } void insert(int k, int x) { e[idx] = x, l[idx] = k, r[idx] = r[k]; l[r[k]] = idx, r[k] = idx++; } void insertHead(int x) { insert(0, x); } void insertTail(int x) { insert(l[1], x); } void deleteNode(int x) { l[r[x]] = l[x], r[l[x]] = r[x]; } int main() { int m = read(); char op[10]; init(); while (m--) { cin >> op; // 这里以后开大一点吧... int x = read(), y = 0; if (op[0] == 'R') insertTail(x); else if (op[0] == 'L') insertHead(x); else if (op[0] == 'D') deleteNode(x + 1); else if (op[1] == 'R') y = read(), insert(x + 1, y); else y = read(), insert(l[x + 1], y); } for (int i = r[0]; i != 1; i = r[i]) O(e[i]); return 0; }
栈 & 队列 & 单调..
模拟栈
雪菜有的是 从 tt=0
不知道有没有影响.
然后empty() 是 tt>0
注意 stk, 和 tt = -1; ???
int stk[N5], tt = -1; //记住下标是从 -1 开始的 void push(int x) { stk[++tt] = x; } void pop() { --tt; } int query() { return stk[tt]; } bool empty() { return tt == -1; }
模拟队列
尾进 头出. tt=-1, hh = 0
int q[N5], tt = -1, hh; void push(int x) { q[++tt] = x; } void pop() { ++hh; } int query() { return q[hh]; } bool empty() { return hh > tt; }
单调栈
输出每个数左边第一个比他小的数. => 单增的栈.
int stk[N6], tt = 0; int main() { int n = read(); rep(i, 0, n) { int x = read(); while (tt && x <= stk[tt]) tt--; O(tt ? stk[tt] : -1); stk[++tt] = x; } return 0; }
单调队列(双端)
滑动窗口最大值和最小值.
int a[N6], q[N6], tt = -1, hh; int main() { int n = read(), k = read(); rep(i, 0, n) a[i] = read(); rep(i, 0, n) { if (hh <= tt && i - k + 1 > q[hh]) hh++; // 如果左边不对, 出栈. while (hh <= tt && a[q[tt]] >= a[i]) tt--; //最小值, 单增区间 q[++tt] = i; if (i - k + 1 >= 0) O(a[q[hh]]); } puts(""); tt = -1, hh = 0; rep(i, 0, n) { if (hh <= tt && i - k + 1 > q[hh]) hh++; while (hh <= tt && a[q[tt]] <= a[i]) tt--; //最大值, 单减区间 q[++tt] = i; if (i - k + 1 >= 0) O(a[q[hh]]); } return 0; }
栈. 表达式求值 ★★★★
不会做... 不过这个顺序..
int stk[N6], tt = 0, top = 0; char op[N6]; void eval() { int y = stk[tt--], x = stk[tt--]; char c = op[top--]; if (c == '*') x = x * y; else if (c == '/') x = x / y; else if (c == '-') x = x - y; else if (c == '+') x = x + y; stk[++tt] = x; } int main() { unordered_map<char, int> um = { {'+', 1}, {'-', 1}, {'*',2},{'/',2} }; // 定义 priority, 小的进栈前大的先完毕 string equ; cin >> equ; rep(i, 0, equ.size()) { char c = equ[i]; if (isdigit(c)) { int x = 0, j = i; while (j < equ.size() && isdigit(equ[j])) { x = x * 10 + equ[j++] - '0'; } i = j - 1; // 因为后面要 i ++; stk[++tt] = x; } else { if (c == '(') op[++top] = c; // 左括号直接进栈. else if (c == ')') { while (op[top] != '(') eval(); //右括号碰到左前一直运算. --top; } else { while (top && op[top] != '(' && um[c] <= um[op[top]]) eval(); //相同情况就可以eval了 // 为什么换成 < 不行呢? // 24 - 5 + 3; 这种 -号需要一定先运算 op[++top] = c; } } } while (top) eval(); O(stk[tt]); return 0; }
KMP ★★★★
其实也不难 不过像个dp么? 或者正确性挺难证明出来的.
int n, m; int ne[N5]; char s[N6], p[N5]; int main() { cin >> n >> p + 1 >> m >> s + 1; for (int i = 2, j = 0; i <= n; i++) { while (j && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j++; //求next 就是子串和自己匹配. ne[i] = j; } da(ne, n + 2); for (int i = 1, j = 0; i <= m; i++) { while (j && s[i] != p[j + 1]) j = ne[j]; if (s[i] == p[j + 1]) j++; if (j == n) { O(i - n); j = ne[j]; } } return 0; }
数组元素的目标和
双指针
int a[N5], b[N5]; int main() { int n = read(), m = read(), x = read(); rep(i, 0, n) a[i] = read(); rep(i, 0, m) b[i] = read(); int r = m - 1; rep(l, 0, n) { while (r >= 0 && a[l] + b[r] > x) r--; if (a[l] + b[r] == x) { O(l), O(r); return 0; } } return 0; }
判断子序列
双指针
int a[N5], b[N5]; int main() { int m = read(), n = read(); int j = 0; rep(i, 0, m) b[i] = read(); rep(i, 0, n) a[i] = read(); rep(i, 0, n) { if (j < m && b[j] == a[i]) j++; } puts(j == m ? "Yes" : "No"); return 0; }
Tire树
Tire 字符串统计
快速 存储字符串集合的数据结构
int son[N5][26], cnt[N5], idx; //idx为0的那个是根 空串 ""; char str[N5]; void insert(char* str) { int p = 0; for (int i = 0; str[i]; i++) { int u = str[i] - 'a'; if (!son[p][u]) son[p][u] = ++idx; p = son[p][u]; } cnt[p]++; } int query(char* str) { int p = 0; for (int i = 0; str[i]; i++) { int u = str[i] - 'a'; if (!son[p][u]) return 0; p = son[p][u]; } return cnt[p]; } int main() { int n = read(); while (n--) { char op[2]; scanf("%s%s", op, str); if (*op == 'I') insert(str); else printf("%d\n", query(str)); } return 0; }
最大异或对.
int a[N5], idx; int son[N6 * 3][2]; //这里为什么需要 N6*3 个? void insert(int x) { int p = 0; per(i, 31, 0) { int& s = son[p][x >> i & 1]; if (!s) s = ++idx; p = s; } } int search(int x) { int p = 0, res = 0; per(i, 31, 0) { int s = x >> i & 1; if (son[p][!s]) { res += 1 << i; //这里为什么是这样子的... p = son[p][!s]; } else p = son[p][s]; } return res; } int main() { int n = read(); rep(i, 0, n)a[i] = read(), insert(a[i]); int res = 0; rep(i, 0, n) { res = max(res, search(a[i])); } O(res); return 0; }
并查集
合并集合
int p[N5]; int find(int k) { if (p[k] != k) p[k] = find(p[k]); return p[k]; } int main() { int n = read(), m = read(); rep(i, 1, n + 1) { p[i] = i; } rep(i, 0, m) { char op[2]; scanf("%s", op); int l = read(), r = read(); if (op[0] == 'M') p[find(l)] = find(r); else puts(find(l) == find(r) ? "Yes" : "No"); } return 0; }
837. 连通块中点的数量
int p[N5], cnt[N5]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { int n = read(), m = read(); rep(i, 1, n + 1) p[i] = i, cnt[i] = 1; rep(i, 0, m) { char op[4]; scanf("%s", op); int l = read(); if (op[0] == 'C') { int r = read(); l = find(l), r = find(r); if (l != r) { cnt[l] += cnt[r]; p[r] = l; } } else if (op[1] == '1') { int r = read(); puts(find(r) == find(l) ? "Yes" : "No"); } else { printf("%d\n", cnt[find(l)]); } } return 0; }
食物链
这篇关于acwing算法基础课II的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享