面试题6:重建二叉树
2014-09-27 17:02
183 查看
题目描述:online
judge
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
输入:
输入可能包含多个测试样例,对于每个测试案例,
输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。
输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。
输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。
输出:
对应每个测试案例,输出一行:
如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。
如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。
样例输入:
样例输出:
问题分析:
性质:二叉树的前序遍历中第一个数字总是根节点的值,中序遍历中根节点把遍历序列分为左右两颗子树。利用者两个特性我们可以重建二叉树。具体如何重建,笔者建议读者自己在草稿纸上举几个例子。弄清楚重建的过程,然后在开始编码。
java代码:
C++代码:
C代码:
测试用例:
普通二叉树(完全二叉树,不完全二叉树)
特殊二叉树(所有结点都没有左结点或右结点的树,只有一个结点的二叉树)
特殊输入测试(二叉树结点为null,输入前序和中序不匹配)
体会:
本人最先开始学的是C语言,对于指针在java中的一些类似功能不是特别熟悉,java
生成的对象不要人为管理,而C和C++需要人为销毁。所以java对于实现树和图等结构比C和C++更加容易。
judge
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
输入:
输入可能包含多个测试样例,对于每个测试案例,
输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。
输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。
输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。
输出:
对应每个测试案例,输出一行:
如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。
如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。
样例输入:
8 1 2 4 7 3 5 6 8 4 7 2 1 5 3 8 6 8 1 2 4 7 3 5 6 8 4 1 2 7 5 3 8 6
样例输出:
7 4 2 5 8 6 3 1 No
问题分析:
性质:二叉树的前序遍历中第一个数字总是根节点的值,中序遍历中根节点把遍历序列分为左右两颗子树。利用者两个特性我们可以重建二叉树。具体如何重建,笔者建议读者自己在草稿纸上举几个例子。弄清楚重建的过程,然后在开始编码。
java代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTokenizer; public class Problem_06 { private int[] preorder; private int[] inorder; private BinaryTreeNode root; private boolean isTree = true; private StringBuilder sb; public Problem_06(int[] preorder, int[] inorder){ this.preorder = preorder; this.inorder = inorder; root = construct(preorder, inorder); sb = new StringBuilder(); } private BinaryTreeNode construct(int[] preorder, int[] inorder) { if(preorder.length == 0 || inorder.length == 0){ isTree = false; return null; } return constructCore(0, preorder.length - 1, 0, inorder.length -1); } private BinaryTreeNode constructCore(int startPreorder, int endPreorder, int startInorder, int endInorder) { int rootValue = preorder[startPreorder]; BinaryTreeNode root = new BinaryTreeNode(); root.value = rootValue; if(startPreorder == endPreorder){ if(startInorder == endInorder && preorder[startPreorder] == inorder[startInorder]){ return root; }else{ isTree = false; return null; } } //从中序遍历中找到根节点 int rootInorder = startInorder; while(rootInorder <= endInorder && inorder[rootInorder] != rootValue){ ++rootInorder; } if(rootInorder > endInorder || (rootInorder == endInorder && inorder[rootInorder] != rootValue)){ isTree = false; return null; } int leftLength = rootInorder - startInorder; int leftPreorder = startPreorder + leftLength; if(leftLength > 0 && isTree){ root.left = constructCore(startPreorder + 1, leftPreorder, startInorder, rootInorder -1 ); } if(leftLength < endPreorder - startPreorder && isTree){ root.right = constructCore(leftPreorder + 1, endPreorder, rootInorder + 1, endInorder); } return root; } private void postTree(BinaryTreeNode root) { if (root.left != null) postTree(root.left); if (root.right != null) postTree(root.right); sb.append(root.value+" "); } public void showTree() { if (isTree) { postTree(root); System.out.println(sb.toString()); } else { System.out.println("No"); } } class BinaryTreeNode{ int value; BinaryTreeNode left; BinaryTreeNode right; } public static void main(String[] args) throws IOException { BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); StreamTokenizer str = new StreamTokenizer(buf); while(str.nextToken() != StreamTokenizer.TT_EOF){//元素录入 int length = (int)str.nval; int preorder[] = new int[length]; int inorder[] = new int[length]; for(int i = 0; i < preorder.length; i ++){ str.nextToken(); preorder[i] = (int)str.nval; } for(int i = 0; i < inorder.length; i ++){ str.nextToken(); inorder[i] = (int)str.nval; } new Problem_06(preorder,inorder).showTree(); } } }
C++代码:
#include<iostream> #include<stdio.h> using namespace std; #define N 10000 struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight; }; bool bo; BinaryTreeNode *ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder) { int rootValue = startPreorder[0]; BinaryTreeNode *root = new BinaryTreeNode(); root->m_nValue = rootValue; root->m_pLeft = root->m_pRight = NULL; if(startPreorder == endPreorder) { if(startInorder == endInorder && *startPreorder == *startInorder) return root; else { bo = false; return NULL; } } int *rootInorder = startInorder; while(rootInorder <= endInorder && *rootInorder != rootValue) { rootInorder++; } if(rootInorder == NULL || *rootInorder != rootValue) { bo = false; return NULL; } int leftLength = rootInorder - startInorder; int *leftPreorderEnd = startPreorder + leftLength; if(leftLength > 0) { root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1); } if(endPreorder - startPreorder > leftLength) { root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder); } return root; } BinaryTreeNode *Construct(int *preorder, int *inorder, int length) { if(preorder == NULL || inorder == NULL || length <= 0) { bo = false; return NULL; } return ConstructCore(preorder, preorder + length -1, inorder, inorder + length -1); } void tailPrint(BinaryTreeNode *root) { if(root->m_pLeft != NULL) tailPrint(root->m_pLeft); if(root->m_pRight != NULL) tailPrint(root->m_pRight); printf("%d ", root->m_nValue); } int main() { int n; while(scanf("%d", &n) != EOF) { bo = true; if(n <= 0) { printf("No\n"); return 0; } int a , b ; for(int i = 0; i < n; i++) { scanf("%d", &a[i]); } for(int j = 0; j < n; j++) { scanf("%d", &b[j]); } BinaryTreeNode *c = Construct(a, b, n); if(bo == true && c != NULL) { tailPrint(c); printf("\n"); } else printf("No\n"); } return 0; }
C代码:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 typedef struct Node { int i; struct Node* left; struct Node* right; }Node; int isNotTree=FALSE; Node* RebuildTree(int* preOrder,int* inOrder,int length) { int i=0; if(isNotTree) return NULL; Node* result=(Node*)malloc(sizeof(Node)); result->left=NULL; result->right=NULL; if(length==0) return NULL; if(length==1) { if(*preOrder!=*inOrder) { isNotTree=TRUE; return NULL; } result->i=*preOrder; return result; } for(;*preOrder!=inOrder[i];++i); result->i=*preOrder; result->left=RebuildTree(preOrder+1,inOrder,i); result->right=RebuildTree(preOrder+i+1,inOrder+i+1,length-i-1); return result; } void printTree(Node* root) { if(root!=NULL) { printTree(root->left); printTree(root->right); printf("%d ",root->i); } } int main() { int length; int *preOrder,*inOrder; int i=0; struct Node* root=NULL; while(scanf("%d",&length)!=EOF) { preOrder=(int*)malloc(length*sizeof(int)); inOrder=(int*)malloc(length*sizeof(int)); for(i=0;i<length;++i) scanf("%d",&preOrder[i]); for(i=0;i<length;++i) scanf("%d",&inOrder[i]); root=RebuildTree(preOrder,inOrder,length); if(isNotTree==TRUE) { printf("No"); isNotTree=FALSE; } else printTree(root); printf("\n"); free(preOrder); free(inOrder); } return 0; }
测试用例:
普通二叉树(完全二叉树,不完全二叉树)
特殊二叉树(所有结点都没有左结点或右结点的树,只有一个结点的二叉树)
特殊输入测试(二叉树结点为null,输入前序和中序不匹配)
体会:
本人最先开始学的是C语言,对于指针在java中的一些类似功能不是特别熟悉,java
生成的对象不要人为管理,而C和C++需要人为销毁。所以java对于实现树和图等结构比C和C++更加容易。
相关文章推荐
- 剑指Offer之面试题6:重建二叉树
- 面试题 6: 重建二叉树
- 《剑指Offer》面试题6 重建二叉树——勘误
- 剑指offer-->面试题6 重建二叉树
- 面试题6:重建二叉树
- 剑指Offer面试题6(Java版):重建二叉树
- 《剑指offer》(面试题6):重建二叉树
- 剑指Offer面试题6重建二叉树(根据前序中序输出后序)
- 剑指offer 面试题6 重建二叉树
- 剑指Offer学习之面试题6 :重建二叉树
- 面试题6:重建二叉树
- 剑指offer-面试题6 重建二叉树
- 【剑指offer】面试题6:重建二叉树
- 面试题五 重建二叉树
- 剑指Offer----面试题六:重建二叉树
- 剑指Offer:面试题6 重建二叉树
- 剑指offer面试题6 重建二叉树(java)
- 《剑指Offer》面试题6:重建二叉树
- 剑指offer--面试题6:重建二叉树--Java实现
- 《剑指Offer》学习笔记--面试题6:重建二叉树