剑指offer笔记面试题7----重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如,输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5 3, 8, 6},则重建如下图所示的二叉树并输出它的头结点。二叉树的节点的定义如下:
struct BinaryTreeNode{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
// 1
// / \
// 2 3
// / / \
// 4 5 6
// \ /
// 7 8
测试用例:
- 普通二叉树(完全二叉树,不完全二叉树)。
- 特殊二叉树(所有节点都没有右子节点的二叉树;所有节点都没有左子节点的二叉树;只有一个节点的二叉树)。
- 特殊的输入测试(二叉树的根节点指针为nullptr;输入的前序遍历序列和中序遍历序列不匹配)。
测试代码:
void Test(char* testName, int* preorder, int* inorder, int length)
{
if(testName != nullptr)
printf("%s begins:\n", testName);
printf("The preorder sequence is: ");
for(int i = 0; i < length; ++ i)
printf("%d ", preorder[i]);
printf("\n");
printf("The inorder sequence is: ");
for(int i = 0; i < length; ++ i)
printf("%d ", inorder[i]);
printf("\n");
try
{
BinaryTreeNode* root = Construct(preorder, inorder, length);
PrintTree(root);
DestroyTree(root);
}
catch(std::exception& exception)
{
printf("Invalid Input.\n");
}
}
// 普通二叉树
// 1
// / \
// 2 3
// / / \
// 4 5 6
// \ /
// 7 8
void Test1()
{
const int length = 8;
int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};
int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};
Test("Test1", preorder, inorder, length);
}
// 所有结点都没有右子结点
// 1
// /
// 2
// /
// 3
// /
// 4
// /
// 5
void Test2()
{
const int length = 5;
int preorder[length] = {1, 2, 3, 4, 5};
int inorder[length] = {5, 4, 3, 2, 1};
Test("Test2", preorder, inorder, length);
}
// 所有结点都没有左子结点
// 1
// \
// 2
// \
// 3
// \
// 4
// \
// 5
void Test3()
{
const int length = 5;
int preorder[length] = {1, 2, 3, 4, 5};
int inorder[length] = {1, 2, 3, 4, 5};
Test("Test3", preorder, inorder, length);
}
// 树中只有一个结点
void Test4()
{
const int length = 1;
int preorder[length] = {1};
int inorder[length] = {1};
Test("Test4", preorder, inorder, length);
}
// 完全二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
void Test5()
{
const int length = 7;
int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
int inorder[length] = {4, 2, 5, 1, 6, 3, 7};
Test("Test5", preorder, inorder, length);
}
// 输入空指针
void Test6()
{
Test("Test6", nullptr, nullptr, 0);
}
// 输入的两个序列不匹配
void Test7()
{
const int length = 7;
int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
int inorder[length] = {4, 2, 8, 1, 6, 3, 7};
Test("Test7: for unmatched input", preorder, inorder, length);
}
本题考点:
- 考查应聘者对二叉树的前序遍历和中序遍历的理解程度。只有对二叉树的不同遍历算法有了深刻的理解,应聘者才有可能在遍历序列中划分出左、右子树对应的子序列。
- 考查应聘者分析复杂问题的能力。我们把构建二叉树的大问题分解成构建左、右子树的两个小问题。我们发现小问题和大问题在本质上是一致的,因此可以用递归的方式解决。
实现代码:
/*********************************BinaryTree.h************************************/
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
BinaryTreeNode* CreateBinaryTreeNode(int value);
void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight);
void PrintTreeNode(const BinaryTreeNode* pNode);
void PrintTree(const BinaryTreeNode* pRoot);
void DestroyTree(BinaryTreeNode* pRoot);
/*********************************BinaryTree.cpp************************************/
#include <cstdio>
#include "BinaryTree.h"
BinaryTreeNode* CreateBinaryTreeNode(int value)
{
BinaryTreeNode* pNode = new BinaryTreeNode();
pNode->m_nValue = value;
pNode->m_pLeft = nullptr;
pNode->m_pRight = nullptr;
return pNode;
}
void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
if(pParent != nullptr)
{
pParent->m_pLeft = pLeft;
pParent->m_pRight = pRight;
}
}
void PrintTreeNode(const BinaryTreeNode* pNode)
{
if(pNode != nullptr)
{
printf("value of this node is: %d\n", pNode->m_nValue);
if(pNode->m_pLeft != nullptr)
printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
else
printf("left child is nullptr.\n");
if(pNode->m_pRight != nullptr)
printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
else
printf("right child is nullptr.\n");
}
else
{
printf("this node is nullptr.\n");
}
printf("\n");
}
void PrintTree(const BinaryTreeNode* pRoot)
{
PrintTreeNode(pRoot);
if(pRoot != nullptr)
{
if(pRoot->m_pLeft != nullptr)
PrintTree(pRoot->m_pLeft);
if(pRoot->m_pRight != nullptr)
PrintTree(pRoot->m_pRight);
}
}
void DestroyTree(BinaryTreeNode* pRoot)
{
if(pRoot != nullptr)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight;
delete pRoot;
pRoot = nullptr;
DestroyTree(pLeft);
DestroyTree(pRight);
}
}
/*********************************ConstructBinaryTree.cpp************************************/
#include "..\Utilities\BinaryTree.h"
#include <exception>
#include <cstdio>
BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);
BinaryTreeNode* Construct(int* preorder, int* inorder, int length)
{
if(preorder == nullptr || inorder == nullptr || length <= 0)
return nullptr;
return ConstructCore(preorder, preorder + length - 1,
inorder, inorder + length - 1);
}
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 = nullptr;
if(startPreorder == endPreorder)
{
if(startInorder == endInorder && *startPreorder == *startInorder)
return root;
else
throw std::exception("Invalid input.");
}
// 在中序遍历中找到根结点的值
int* rootInorder = startInorder;
while(rootInorder <= endInorder && *rootInorder != rootValue)
++ rootInorder;
if(rootInorder == endInorder && *rootInorder != rootValue)
throw std::exception("Invalid input.");
int leftLength = rootInorder - startInorder;
int* leftPreorderEnd = startPreorder + leftLength;
if(leftLength > 0)
{
// 构建左子树
root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd,
startInorder, rootInorder - 1);
}
if(leftLength < endPreorder - startPreorder)
{
// 构建右子树
root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
rootInorder + 1, endInorder);
}
return root;
}
int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
int a;
scanf("%d", &a);
return 0;
}
剑指offer笔记面试题7----重建二叉树的更多相关文章
- 《剑指offer》面试题6 重建二叉树 Java版
(由一个二叉树的前序和中序序列重建一颗二叉树) 书中方法:我们要重建一棵二叉树,就要不断地找到根节点和根节点的左子结点和右子节点.注意前序序列, 它的第一个元素就是二叉树的根节点,后面的元素分为它的左 ...
- 【剑指Offer】面试题07. 重建二叉树
题目 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 ...
- 《剑指offer》面试题07. 重建二叉树
问题描述 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍 ...
- 剑指Offer(书):重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2, ...
- 剑指Offer(四):重建二叉树
一.前言 刷题平台:牛客网 二.题目 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6, ...
- 剑指offer笔记面试题2----实现Singleton模式
题目:设计一个类,我们只能生成该类的一个实例. 解法一:单线程解法 //缺点:多线程情况下,每个线程可能创建出不同的的Singleton实例 #include <iostream> usi ...
- 剑指offer笔记面试题1----赋值运算符函数
题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数. class CMyString{ public: CMyString(char* pData = nullptr); CMyS ...
- 剑指offer笔记面试题3----数组中重复的数字
题目一:找出数组中重复的数字.在一个长度为n的数组里的所有数字都在0~n-1的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中任意一个重复的数字.例如 ...
- 剑指offer笔记面试题4----二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 测试用例: 二维数组中包含 ...
随机推荐
- <算法基础><排序>三种高级排序——快速排序,堆排序,归并排序
这三种排序算法的性能比较如下: 排序名称 时间复杂度(平均) 时间复杂度(最坏) 辅助空间 稳定性 快速排序 O(nlogn) O(n*n) O(nlogn) 不稳定 堆排序 O(nlogn) O(n ...
- 【立即报名】解码AI大杀器:华为云GPU+Tensorflow 容器实战
导语: 人工智能的火热,带来了一波学习TensorFlow深度学习框架的热潮.聊深度学习免不了要用GPU,但目前GPU费用较高,对于个人学习者和创业公司来讲的话,按需配置的云GPU服务器是一个不错的选 ...
- 安装破解版IntelliJ IDEA
1.下载IntelliJ IDEA http://www.jetbrains.com/idea/download/#section=windows 选择Ultimate版本 2.注册码破解 http: ...
- 超详细实操教程!在现有K8S集群上安装JenkinsX,极速提升CI/CD体验!
在2018年年初,Jenkins X首次发布,它由Apache Groovy语言的创建者Jame Strachan创建.Jenkins X 是一个高度集成化的 CI/CD 平台,基于 Jenkins ...
- [Asp.net core 3.1] 通过一个小组件熟悉Blazor服务端组件开发
通过一个小组件,熟悉 Blazor 服务端组件开发.github 一.环境搭建 vs2019 16.4, asp.net core 3.1 新建 Blazor 应用,选择 asp.net core 3 ...
- iOS本地数据存储
http://www.jianshu.com/p/a3eeae99e902 大牛整理的超全
- 胸部CT提取分割肺部
1. 肺部分割提取简介 在处理胸部CT时,我们常常需要获取肺部的一个mask,也就是将肺部结构从数据中提取出来.二维图像还好说,但是三维图像就会变得复杂复杂一点.肺部的分割常常做后续操作的预处理,所以 ...
- acm模板总结
模板链接 字符串模板 KMP EXKMP Trie 可持久化Trie树+DFS序 01Trie Manacher 字符串哈希 2019上海网络赛G题 17 SA(后缀数组) 最大不重叠相似子串 求两 ...
- Python3 多线程爬取梨视频
多线程爬取梨视频 from threading import Thread import requests import re # 访问链接 def access_page(url): respons ...
- JAVA中SPI机制
之前研究dubbo的时候就很好奇,里面各种扩展机制,期间也看过很多关于SPI的机制,今日有缘再度看到有文章总结,故记录一下, 首先了解一下 JAVA中SPI简单的用法 可参考这篇文章,https:// ...