题目传送门

终于遇到了LCA题,先复习一下LCA模板
题目中提到的key值取值范围在int之内,不能直接视为结点编号
我将preorder的index作为结点编号,即认为结点的前序遍历为1…n
同时使用map记录key值和结点编号的对应关系

一开始在建树的时候,没有想明白怎么给结点编号
竟然傻到用一个全局变量累加给结点编号,这样回溯的时候全局变量已经累加,就不对了

测试点4、5WA掉,竟是因为数组开的不够大(10000->10005)

其实这道题没有必要建树,我们只要得到结点的deep就可以了
学习一下柳神不用建树的姿势

建树

struct node {int lc;int rc;int x;
};
node T[N + 1];//按照preorder的index规定结点编号
int build(int pre1,int pre2,int in1,int in2,int dp) {int id = pre1;T[id].x = preorder[pre1];Tmap[preorder[pre1]] = id;      //key -> nodeT[id].lc = T[id].rc = -1;deep[id] = dp;if (pre1 == pre2) return id;int index = find(preorder[pre1], in1, in2);int left_sz = index - in1;int right_sz = in2 - index;if (left_sz > 0) {T[id].lc = build(pre1 + 1, pre1 + left_sz, in1, index - 1, dp + 1);f[T[id].lc][0] = id;}if (right_sz > 0) {T[id].rc = build(pre1 + left_sz + 1, pre2, index + 1, in2, dp + 1);f[T[id].rc][0] = id;}return id;
}

AC代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<cmath>
using namespace std;const int N = 10005;
map<int, int>Tmap;
int n, m, root;
int preorder[N + 1];
int inorder[N + 1];
int deep[N + 1];
int f[N][20], mj;int find(int x,int s,int t) {for (int i = s; i <= t; ++i)if (inorder[i] == x) return i;
}//按照preorder的index规定结点编号
void build(int pre1,int pre2,int in1,int in2,int dp) {int id = pre1;Tmap[preorder[pre1]] = id;      //key -> nodedeep[id] = dp;if (pre1 == pre2) return;int index = find(preorder[pre1], in1, in2);int left_sz = index - in1;int right_sz = in2 - index;int lc = pre1 + 1;int rc = pre1 + left_sz + 1;if (left_sz > 0) {build(pre1 + 1, pre1 + left_sz, in1, index - 1, dp + 1);f[lc][0] = id;}if (right_sz > 0) {build(pre1 + left_sz + 1, pre2, index + 1, in2, dp + 1);f[rc][0] = id;}
}int lca(int x, int y) {if (deep[x] < deep[y]) swap(x, y);int d = deep[x] - deep[y];if (d)for (int i = 0; i <= mj && d; i++, d >>= 1)if (d & 1)x = f[x][i];if (x == y) return x;for (int i = mj; i >= 0; i--)if (f[x][i] != f[y][i]) {x = f[x][i];y = f[y][i];}return f[x][0];
}int main()
{scanf("%d%d",&m,&n);for (int i = 1; i <= n; ++i) scanf("%d", &inorder[i]);for (int i = 1; i <= n; ++i) scanf("%d", &preorder[i]);build(1,n,1,n,1);mj = (int)(log(n) / log(2)) + 1;for (int i = 1; i <= mj; ++i)for (int j = 1; j <= n; ++j)f[j][i] = f[f[j][i - 1]][i - 1];for (int i = 1; i <= m; ++i) {int x, y;scanf("%d%d", &x, &y);map<int, int>::iterator node1 = Tmap.find(x);map<int, int>::iterator node2 = Tmap.find(y);if (node1 == Tmap.end() && node2 == Tmap.end()) {printf("ERROR: %d and %d are not found.\n",x,y);}else if (node1 == Tmap.end() && node2 != Tmap.end()) {printf("ERROR: %d is not found.\n", x);}else if (node1 != Tmap.end() && node2 == Tmap.end()) {printf("ERROR: %d is not found.\n", y);}else {int ans = lca(Tmap[x], Tmap[y]);if (ans == Tmap[x]) {printf("%d is an ancestor of %d.\n", x, y);}else if (ans == Tmap[y]) {printf("%d is an ancestor of %d.\n", y, x);}else {printf("LCA of %d and %d is %d.\n", x, y, preorder[ans]);}}}return 0;
}

PAT (Advanced Level) 1151——前序中序构造树+LCA+map ( Ps.数组开大点啊 )相关推荐

  1. java前中后序_前序中序求后序的java算法

    二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树: 中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树: 后序遍历:对任一子树, ...

  2. pat根据中序遍历和先序遍历_[leetcode/lintcode 题解] 前序遍历和中序遍历树构造二叉树...

    [题目描述] 根据前序遍历和中序遍历树构造二叉树. 在线评测地址: 九章算法 - 帮助更多中国人找到好工作,硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧​www.jiuzhang.com [样例 ...

  3. 二叉树题目 ----7 前序中序遍历构造二叉树

    前序中序遍历构造二叉树 思路 在前序中找根结点 根据根结点 + 中序,分成左右两棵子树 根据子树长度,把前序分成左右两颗子树 递归处理子树 /*** Definition for a binary t ...

  4. LintCode-73.前序遍历和中序遍历树构造二叉树

    前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 注意事项 你可以假设树中不存在相同数值的节点 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树: 2 ...

  5. 根据前序和中序构造整个二叉树

    根据前序和中序构造整个二叉树 前序遍历:根 左 右 中序遍历:左 根 右 先根据前序遍历,得到根节点3,然后看中序遍历,可以知道9是3的左孩子[15,20,7]是3的右孩子 再去先序遍历的到9,再到中 ...

  6. 二叉树的构造(前序+中序)---(后序 + 中序)

    二叉树的构造(前序+中序)-(后序 + 中序) 思路:要对前序+中序(后序+中序)的构建树的动态过程要了解,思路比较简单,在了解了这个过程之后,理解下面代码就容易了. 过程 参考图: 前序 + 中序: ...

  7. 前序中序、中序后序以及前序后序构造二叉树

    文章目录 前序中序 中序后序 前序后序 定义的树节点如下, class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { ...

  8. 通过前序中序,中序后序,前序后序来构造一二叉树

    前序中序,以及中序后序可以确定唯一一颗二叉树,而前序后续是可以有多种情况,因为仅仅前序后续是无法确定根节点左右子树的问题: 首先解决通过前序和中序来构建一颗二叉树的问题: 前序=根节点+左子树+右子树 ...

  9. 根据前序和后序遍历构造二叉树(附前序中序代码)

    889. 根据前序和后序遍历构造二叉树 前序和中序 道理相同 改变一些细节就可以了,在最后附上了前序中序的代码 题目描述 返回与给定的前序和后序遍历匹配的任何二叉树. pre 和 post 遍历中的值 ...

最新文章

  1. 深度学习实战—基于TensorFlow 2.0的人工智能开发应用
  2. access哪个速度快 vfp_大学计算机二级考试,报考哪个科目比较好?
  3. java实现人字拼,地板怎么玩花式人字拼铺法 人字拼地板家居实例图
  4. python3.6.4安装教程-centos7中安装python3.6.4的教程
  5. 遇到的问题锦集及解决方案
  6. 组件通信 Provideinject
  7. 【安全研究】从mimikatz学习万能密码——上
  8. python:sort,sorted,argsort,lexsort
  9. 使用VS2019编写C语言程序,环境安装配置+代码调试
  10. c#控制台应用程序,如何实现隐藏DOS窗口
  11. 工作218:页面样式调整
  12. python中的get函数_python之函数用法get()
  13. 红帽资深解决方案架构师魏新宇:云原生应用构建之路
  14. Python 打开目录与指定文件
  15. 【智力题】拿硬币(数数字)、游戏
  16. iview的select联动_render函数渲染的iview中的Select组件如何联动?
  17. 暴风激活工具,劫持Chrome浏览器主页
  18. CHROME插件开发之·web页面与插件后台通信(chrome.runtime.sendMessage => chrome.runtime.onMessageExternal.addListener)
  19. linux写makefile用tab报错,隐含规则 - linux makefile教程
  20. 裴波那契数列python

热门文章

  1. 自博(Frist Blog)
  2. 3D建模培训学习内容和学习方法盘点
  3. 关于Excel在VB里的应用(来自微软)
  4. 【优矿学习】分析新用户引导的代码
  5. 宝妈适合学计算机方面的什么,适合宝妈的成考专业 学什么专业前景好
  6. 基于labview的心率测量系统设计(适用于其他串口通信的数据传输,改动一下程序即可)...
  7. 用循环实现连续大写英文字母的输出
  8. OpenCV入门(12):颜色反转
  9. 中关村推出“1+6”系列先行先试改革政策
  10. lol提示游戏环境异常重启计算机,小编教你lol游戏环境异常请重启机器该怎么办...