蓝桥杯练习题库——试题 算法训练 绘制地图(二分法递归求解)
题目:
试题 算法训练 绘制地图
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
最近,WYF正准备参观他的点卡工厂。WYF集团的经理氰垃圾需要帮助WYF设计参“观”路线。现在,氰垃圾知道一下几件事情:
1.WYF的点卡工厂构成一颗二叉树。
2.一共有n座工厂。
3.他需要把这颗树上的点以后序遍历的方法列出来,才能绘制地图。
还好,最近他的属下给了他先序遍历和中序遍历的数据。可是,氰垃圾最近还要帮㊎澤穻解决一些问题,没有时间。请你帮帮他,替他完成这项任务。由于氰垃圾的一些特殊的要求,WYF的参观路线将会是这棵树的后序遍历。
1.WYF的点卡工厂构成一颗二叉树。
2.一共有n座工厂。
3.他需要把这颗树上的点以后序遍历的方法列出来,才能绘制地图。
还好,最近他的属下给了他先序遍历和中序遍历的数据。可是,氰垃圾最近还要帮㊎澤穻解决一些问题,没有时间。请你帮帮他,替他完成这项任务。由于氰垃圾的一些特殊的要求,WYF的参观路线将会是这棵树的后序遍历。
输入格式
第一行一个整数n,表示一共又n座工厂。
第二行n个整数,表示先序遍历。
第三行n个整数,表示中序遍历。
第二行n个整数,表示先序遍历。
第三行n个整数,表示中序遍历。
输出格式
输出共一行,包含n个整数,为后序遍历。
样例输入
8
1 2 4 5 7 3 6 8
4 2 7 5 1 8 6 3
1 2 4 5 7 3 6 8
4 2 7 5 1 8 6 3
样例输出
4 7 5 2 8 6 3 1
数据规模和约定
0<n<100000,。保证先序遍历和中序遍历合法,且均为1~n。
Java代码:
package com.lzp.algorithmpractice.p13; import java.util.Scanner; /** * @Author LZP * @Date 2021/3/11 13:36 * @Version 1.0 * 试题 算法训练 绘制地图 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 最近,WYF正准备参观他的点卡工厂。WYF集团的经理氰垃圾需要帮助WYF设计参“观”路线。现在,氰垃圾知道一下几件事情: 1.WYF的点卡工厂构成一颗二叉树。 2.一共有n座工厂。 3.他需要把这颗树上的点以后序遍历的方法列出来,才能绘制地图。 还好,最近他的属下给了他先序遍历和中序遍历的数据。可是,氰垃圾最近还要帮㊎澤穻解决一些问题,没有时间。请你帮帮他,替他完成这项任务。由于氰垃圾的一些特殊的要求,WYF的参观路线将会是这棵树的后序遍历。 输入格式 第一行一个整数n,表示一共又n座工厂。 第二行n个整数,表示先序遍历。 第三行n个整数,表示中序遍历。 输出格式 输出共一行,包含n个整数,为后序遍历。 样例输入 8 1 2 4 5 7 3 6 8 4 2 7 5 1 8 6 3 样例输出 4 7 5 2 8 6 3 1 数据规模和约定 0<n<100000,。保证先序遍历和中序遍历合法,且均为1~n。 采用二分策略,递归求解 */ public class Main { private static int[] front; private static int[] mid; private static int[] dp = new int[100000 + 10]; private static int n; public static void main(String[] args) { Scanner input = new Scanner(System.in); n = input.nextInt(); front = new int[n]; mid = new int[n]; for (int i = 0; i < n; i++) { front[i] = input.nextInt(); } for (int i = 0; i < n; i++) { int temp = input.nextInt(); mid[i] = temp; /* dp数组在这里的作用就是记录中序遍历序列中数的索引值,方 便后面直接通过数组下标获取,不用每一次都要为了拿一个数 据而去遍历整个中序遍历序列 */ dp[temp] = i; } f(); } public static void f() { Node tree = division(dp[front[0]], 0, 0, n - 1); laterAccess(tree); } /** * 递归 * 这里的parent是为了找到根节点在中序遍历序列中的索引,cur是在当前前序遍历中指针指向的位置, * 它的传入是在递归的过程中为了方便找左右孩子,start、end是两个边界的索引 * @param parent * @param cur * @param start * @param end * @return */ public static Node division(int parent, int cur, int start, int end) { // 递归的出口 if (start == end) { return new Node(mid[parent], null, null); } if (start > end) { return null; } Node left = null; Node right = null; if (cur + 1 >= 0) { // 找左孩子 left = division(dp[front[cur + 1]], cur + 1, start, parent - 1); } if (cur + 1 + (parent - start) < n) { // 找右孩子 right = division(dp[front[cur + 1 + (parent - start)]], cur + 1 + (parent - start), parent + 1, end); } // 创建并返回父亲节点 return new Node(mid[parent], left, right); } /** * 后序遍历 * @param tree 树的根节点 */ public static void laterAccess(Node tree) { if (tree != null) { laterAccess(tree.left); laterAccess(tree.right); System.out.print(tree.data + " "); } } } class Node { int data; Node left; Node right; public Node(int data, Node left, Node right) { this.data = data; this.left = left; this.right = right; } }