PAT甲级刷题记录-(AcWing)-(Day06树 8题)

课程来源AcWing
其中AcWing中的题目为翻译好的中文题目

今日刷题列表

  • 1110 Complete Binary Tree
  • 1115 Counting Nodes in a Binary Search Tree
  • 1119 Pre- and Post-order Traversals
  • 1127 ZigZagging on a Tree
  • 1138 Postorder Traversal
  • 1066 Root of AVL Tree
  • 1123 Is It a Complete AVL Tree
  • 1135 Is It A Red-Black Tree

1110 Complete Binary Tree

AcWing链接
PAT链接

注意点

  • 一开始在读入节点的时候我用了chara-'0'来存储,因为粗心没看到题目中可能出现大于10的节点编号,后来改为string就可以了
  • stoi()可以很方便的把string类型的字符串转为int
#include <iostream>
#include <cstring>
#include <algorithm>const int N = 30;
using namespace std;
int l[N], r[N];
int n, last_idx, last_node, root = 0;
bool is_father[N];void dfs(int u, int k) {// u代表当前节点,k代表完全二叉树中的节点if (u == -1) return;if (k > last_idx) {last_idx = k;last_node = u;}dfs(l[u], 2 * k);dfs(r[u], 2 * k + 1);
}int main() {cin >> n;memset(l, -1, sizeof(l));memset(r, -1, sizeof(r));for (int i = 0; i < n; ++i) {string a, b;cin >> a >> b;if (a != "-") l[i] = stoi(a), is_father[l[i]] = true;if (b != "-") r[i] = stoi(b), is_father[r[i]] = true;}while (is_father[root]) root++;dfs(root, 1);if (last_idx == n) cout << "YES " << last_node;else cout << "NO " << root;return 0;
}

1115 Counting Nodes in a Binary Search Tree

AcWing链接
PAT链接

注意点

  • 这边在插入的时候使用&u, 可以更新一开始传人的root值,也可以改变之后递归中l[u],r[u]的值
#include <iostream>
#include <cstring>using namespace std;
const int N = 1010;
int l[N], r[N], val[N], idx = 0;
int cnt[N];
int max_depth;void insert(int &u, int w) {if (u == 0) {u = ++idx;cout << "u = " << u << endl;val[u] = w;} else if (w <= val[u]) insert(l[u], w);else insert(r[u], w);
}void dfs(int root, int depth) {if (root == 0) return;max_depth = max(depth, max_depth);cnt[depth]++;dfs(l[root], depth + 1);dfs(r[root], depth + 1);
}int main() {int n;cin >> n;int root = 0;for (int i = 0; i < n; ++i) {int x;cin >> x;insert(root, x);cout << root << endl;cout << "*****************" << endl;}dfs(root, 0);int n1 = cnt[max_depth];int n2 = cnt[max_depth - 1];printf("%d + %d = %d\n", n1, n2, n1 + n2);return 0;
}

!!! 1119 Pre- and Post-order Traversals

AcWing链接
PAT链接

英语单词

解析
难点在与递归以及暴力遍历前序遍历的序列,找左右的分界点.

#include <cstring>
#include <iostream>const int N = 40;
using namespace std;
int pre[N], post[N];int dfs(int prel, int prer, int postl, int postr, string &s) {if (prel > prer) return 1;if (pre[prel] != post[postr]) return 0;int cnt = 0;for (int i = prel; i <= prer; ++i) {string lin, rin;int lcnt = dfs(prel + 1, i, postl, postl + i - prel - 1, lin);int rcnt = dfs(i + 1, prer, postl + i - prel, postr - 1, rin);if (lcnt && rcnt) {s = lin + to_string(pre[prel]) + " " + rin;cnt += lcnt * rcnt;if (cnt > 1)break;}}return cnt;
}int main() {int n;cin >> n;for (int i = 0; i < n; ++i) {cin >> pre[i];}for (int i = 0; i < n; ++i) {cin >> post[i];}string res;int cnt = dfs(0, n - 1, 0, n - 1, res);if (cnt == 1) puts("Yes");else puts("No");res.pop_back();puts(res.c_str());return 0;
}

1127 ZigZagging on a Tree

AcWing链接
PAT链接

英语单词

  • naive 天真
  • alternating 交替的,交互的
    解析
    与1020题类似,只不过这道题在层序遍历的时候要按层数选择反转后记录当前的遍历序列
    注意点
    l.count(t)找的是哈希表l中键为t的个数,如果存在的话再把l[t]加入队列
#include <cstring>
#include <iostream>
#include <unordered_map>
#include <algorithm>const int N = 40;
using namespace std;
unordered_map<int, int> l, r, pos;
int inorder[N], post[N];
int q[N];
int n;int build(int il, int ir, int pl, int pr) {int root = post[pr];int k = pos[root];if (il < k) l[root] = build(il, k - 1, pl, pl + k - 1 - il);if (k < ir) r[root] = build(k + 1, ir, pl + k - il, pr - 1);return root;
}void bfs(int root) {q[0] = root;int head = 0, tail = 0;int step = 0;while (head <= tail) {int cur_head = head, cur_tail = tail;while (head <= cur_tail) {int t = q[head++];if (l.count(t)) q[++tail] = l[t];if (r.count(t)) q[++tail] = r[t];}if (++step % 2 == 1) reverse(q + cur_head, q + cur_tail + 1);}cout << q[0];for (int i = 1; i < n; ++i) {cout << " " << q[i];}
}int main() {cin >> n;for (int i = 0; i < n; ++i) cin >> inorder[i], pos[inorder[i]] = i;for (int i = 0; i < n; ++i) cin >> post[i];int root = build(0, n - 1, 0, n - 1);bfs(root);return 0;
}

1138 Postorder Traversal

AcWing链接
PAT链接

注意点

没使用哈希表的写法,能过测试点,但是测试点4花了341 ms

#include <iostream>const int N = 50010;
using namespace std;
int pre[N], in[N];
int l[N], r[N];
int n;
int post = 0, flag = 1;void build(int il, int ir, int pl, int pr) {if (flag == 0) return;int root = pre[pl];int k;for (int i = il; i <= ir; ++i) {if (in[i] == root) {k = i;break;}}if (il < k) build(il, k - 1, pl + 1, pl + 1 + k - 1 - il);if (k < ir) build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr);if (post == 0) {post = root;cout << post;flag = 0;return;}
}int main() {cin >> n;for (int i = 0; i < n; ++i)cin >> pre[i];for (int i = 0; i < n; ++i)cin >> in[i];build(0, n - 1, 0, n - 1);return 0;
}

使用了哈希表的写法,测试点4只花了34 ms

#include <iostream>
#include <unordered_map>const int N = 50010;
using namespace std;
int pre[N], in[N];
unordered_map<int, int> l, r, pos;
int n;
int post = 0, flag = 1;void build(int il, int ir, int pl, int pr) {if (flag == 0) return;int root = pre[pl];int k = pos[root];if (il < k) build(il, k - 1, pl + 1, pl + 1 + k - 1 - il);if (k < ir) build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr);if (post == 0) {post = root;cout << post;flag = 0;return;}
}int main() {cin >> n;for (int i = 0; i < n; ++i)cin >> pre[i];for (int i = 0; i < n; ++i)cin >> in[i], pos[in[i]] = i;build(0, n - 1, 0, n - 1);return 0;
}

1066 Root of AVL Tree

AcWing链接
PAT链接

英语单词

  • differ by 相差

解析
下图我画出了二叉树右旋的过程,左旋反一下就好

注意点

  • height_differ(r[u]) == -1计算右子树那边该不该左旋的时候一个rl写错了,找了半天bug
  • 主要考点还是该不该旋, 理解上图即可
#include <iostream>const int N = 30;
using namespace std;
int l[N], r[N], v[N], h[N], idx;void update(int u) {h[u] = max(h[l[u]], h[r[u]]) + 1;
}void R(int &u) {// 右旋int p = l[u];l[u] = r[p];r[p] = u;update(u);update(p);u = p;
}void L(int &u) {int p = r[u];r[u] = l[p];l[p] = u;update(u);update(p);u = p;
}int height_differ(int u) {// 计算左右子树的差return h[l[u]] - h[r[u]];
}void insert(int &u, int w) {if (!u) {u = ++idx;v[u] = w;} else if (w < v[u]) {// 插入左子树insert(l[u], w);// 检查是否要旋if (height_differ(u) == 2) {// 插入左子树之后可能造成左子树高度多一些if (height_differ(l[u]) == 1) {// 左子树的左子树高于右子树, 直接右旋即可R(u);} else {// 左子树的右子树高于左子树的左子树,先左旋再右旋L(l[u]);R(u);}}} else {// 插入右子树insert(r[u], w);// 检查是否要旋if (height_differ(u) == -2) {// 插入右子树之后可能造成右子树高度多一些if (height_differ(r[u]) == -1) {// 右子树的右子树高于左子树, 直接左旋即可L(u);} else {// 右子树的左子树高于右子树的右子树,先右旋再左旋R(r[u]);L(u);}}}update(u);
}int main() {int n, root = 0;cin >> n;for (int i = 0; i < n; ++i) {int w;cin >> w;insert(root, w);}cout << v[root] << endl;return 0;
}

1123 Is It a Complete AVL Tree

AcWing链接
PAT链接

解析

  • 综合基础题,其中构建平衡二叉树的过程和上一题一模一样
  • 在实现层序遍历的过程中,使用pos来记录每个节点的下标(是他们父亲节点的两倍或者两倍+1) 判断下表是否超过n, 如果n个节点的下标都没超过n,那么一定是完全二叉树.
#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>const int N = 30;
using namespace std;
int n;
int l[N], r[N], v[N], h[N], idx;
int q[N], pos[N];void update(int u) {h[u] = max(h[l[u]], h[r[u]]) + 1;
}void L(int &u) {// 左旋int p = r[u];r[u] = l[p];l[p] = u;update(u);update(p);u = p;
}void R(int &u) {// 左旋int p = l[u];l[u] = r[p];r[p] = u;update(u);update(p);u = p;
}int differ_height(int u) {// 返回左右子树高度差return h[l[u]] - h[r[u]];
}void insert(int &u, int w) {if (!u) {u = ++idx;v[u] = w;} else if (w < v[u]) {//插入左insert(l[u], w);if (differ_height(u) == 2) {if (differ_height(l[u]) == 1) R(u);else L(l[u]), R(u);}} else {insert(r[u], w);if (differ_height(u) == -2) {if (differ_height(r[u]) == -1) L(u);else R(r[u]), L(u);}}update(u);
}bool bfs(int root) {q[0] = root;int k = 1;pos[root] = 1;int head = 0, tail = 0;while (head <= tail) {int t = q[head++];if (pos[t] > n) return false;if (l[t]) q[++tail] = l[t], pos[l[t]] = 2 * pos[t];if (r[t]) q[++tail] = r[t], pos[r[t]] = 2 * pos[t] + 1;}return true;
}int main() {cin >> n;memset(h, -1, sizeof(h));int root = 0;for (int i = 0; i < n; ++i) {int w;cin >> w;insert(root, w);}bool res = bfs(root);cout << v[q[0]];for (int i = 1; i < n; ++i) {cout << ' ' << v[q[i]];}cout << endl;if (res) cout << "YES" << endl;else cout << "NO" << endl;return 0;
}

!!! 1135 Is It A Red-Black Tree

AcWing链接
PAT链接

英语单词

  • simple paths 简单路径
  • descendant leaves 后代节点

注意点

  • 在构建平衡二叉树的过程中判断是否为红黑树
#include <iostream>
#include <algorithm>
#include <unordered_map>const int N = 40;
using namespace std;
int n, k;
int pre[N], in[N];
unordered_map<int, int> pos;
bool res;int build(int il, int ir, int pl, int pr, int &sum) {int root = pre[pl];int index = pos[abs(root)];if (index > ir || index < il) {res = false;return 0;}int left = 0, right = 0, left_sum = 0, right_sum = 0;if (il < index) left = build(il, index - 1, pl + 1, pl + 1 + index - 1 - il, left_sum);if (index < ir) right = build(index + 1, ir, pl + 1 + index - 1 - il + 1, pr, right_sum);if (left_sum != right_sum) res = false;sum = left_sum;if (root < 0) {if (left < 0 || right < 0) res = false;} else sum++;return root;
}int main() {cin >> k;while (k--) {cin >> n;for (int i = 0; i < n; ++i) {cin >> pre[i];in[i] = abs(pre[i]);}sort(in, in + n);pos.clear();for (int i = 0; i < n; ++i) {pos[in[i]] = i;}res = true;int sum = 0;int root = build(0, n - 1, 0, n - 1, sum);if (root < 0) res = false;if (res) puts("Yes");else puts("No");}return 0;
}

模板

AcWing链接
PAT链接

英语单词

解析

注意点


PAT甲级刷题记录-(AcWing)-(Day06树 8题)相关推荐

  1. PAT甲级题目翻译+答案 AcWing(树)

    1004 Counting Leaves (30 分) 题意 : 家庭关系可以用家谱树来表示,给定一个家谱树,你的任务是找出其中没有孩子的成员. 第一行包含一个整数 N 表示树中结点总数以及一个整数 ...

  2. 小峰峰的pat甲级刷题记录1020

    小峰峰的pat甲级刷题记录1020 方法一:通过后序和中序序列构建树,再层序输出 #include<iostream> #include<vector> using names ...

  3. 小峰峰的pat甲级刷题记录1030

    很经典的最优路线问题 方法一:dfs 思路: 1.vector数组记录邻居关系用于深搜遍历 2.遍历过程中优化mindis_to[ ] ,fee[ ] 3.遍历过程中记录当前路径path 4.到达终点 ...

  4. PAT甲级刷题笔记(4)

    map专题 61. 火星数字(1011) 本题要求实现火星数字和地球数字间的转换,核心任务有: (1)如何读入,N给定了读入数据个数,但是每个数据有几位数,是数字还是字母不确定: -->同一用字 ...

  5. PAT甲级题目翻译+答案 AcWing(数学)

    1059 Prime Factors (25 分) 题意 : 给一正整数,要求分解质因数 思路 : 使用is_first,来完成除了第一个质因数前都有*的效果 如果n=1,要特判 最后如果n>1 ...

  6. PAT甲级题目翻译+答案 AcWing(排序)

    1012 The Best Rank (25 分) 题意 :给ID和3门成绩,计算其平均分A,输出每位学生最好的排名,A>C>M>E 思路 :如果将所需的若干个元素中使第一个元素为后 ...

  7. PAT甲级题目翻译+答案 AcWing(字符串处理)

    1001 A+B Format (20 分) 题意 :将整数转换成标准格式 思路 :从后往前遍历字符串进行模拟,每三个数字加一个逗号,但不能是在最前面加逗号,也不能是加在负号后面 #include & ...

  8. PAT甲级题目翻译+答案 AcWing(并查集)

    1013 Battle Over Cities (25 分) 题意 :给图,问去掉所询问的一个点后,需要添加多少条边可以使图连通,N<1000N<1000N<1000 思路 :并查集 ...

  9. PAT甲级题目翻译+答案 AcWing(模拟)

    1008 Elevator (20 分) 思路 :last可能等于cur,而无论是否相等,res都是+5的 #include <iostream>using namespace std;i ...

最新文章

  1. 深入浅出多线程系列之四:简单的同步 lock
  2. 判断文件是否为可执行程序
  3. Python 分布式文件系统 Mongodb GridFS
  4. Java多线程笔记(一):JMM与基础关键字
  5. hfss仿真软件入门教程
  6. PowerDesigner详细安装教程
  7. wifi信号桥怎么设置_用手机怎么桥设置桥接无线路由器?(步要祥细)
  8. 华北电力计算机技术考研难度,华北电力大学(专业学位)计算机技术考研难吗
  9. 安装Windows XP出现0X0000007B的解决方法
  10. .NET选择模板添加书签导出Word文档,Web导出至Excel。WordHelp类和ExcelHelp类
  11. 3D旋转相册炫酷js特效
  12. JS实现获取汉字首字母拼音、全拼音及混拼音的方法
  13. 20189217 2018-2019-2 《密码与安全新技术专题》第11周作业
  14. 空间3点求三点所在空间圆的圆心空间坐标
  15. 论文笔记 EMNLP 2021|Modeling Document-Level Context for Event Detection via Important Context Selection
  16. 从企业微信、钉钉、班聊、纷享逍客,看企业服务
  17. 2017年Android第三方框架排行榜
  18. 树莓派3下Python调用斑马GK888t打印机
  19. 人工智能中的分析学快速入门之知识体系
  20. Python的注释快捷键方法

热门文章

  1. 科普 | 区块链概念最全解析:区块链的下一个十年什么样?
  2. 零基础Unreal Engine 4(UE4)图文笔记之准备篇(一)
  3. Xcode The 'Apple Push Notification' feature is only available to users enrolled in Apple Develo.
  4. 明星粉丝经济“叫好不叫座”?变现需找准“窍门儿”
  5. Android下拉列表框
  6. 应急响应 | Windows事件ID及解释大全
  7. PWM波启动无源蜂鸣器——基于STM32MP157A
  8. touch——创建文件
  9. linux下raid1数据恢复,在linux下做RAID1试验
  10. 前端大全(基础总结)(根据js权威指南扩展)