剑指offer-第四章解决面试题的思路(二叉树的镜像)
题目:请完成函数,输入一个二叉树,该函数输出它的镜像。
思路:可能没有听说过书的镜像,但是可以通过画图等来找灵感。就像照镜子一样,人的左边和右边交换了。
如图:

通过如下图变化就可以由左图得到右图:

总体来说:将所有的非叶子节点的左右子树交换。由于交换的过程惊人的一直,因此可以采用递归。
C++代码:
#include<iostream>
using namespace std;
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
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
throw std::exception("Invalid put!");
}
//通过中序遍历序列找到根节点
int* rootInorder=startInorder;
while(rootInorder<=endInorder&&*rootInorder!=rootValue)
{
++rootInorder;
}
if(rootInorder==endInorder&&*rootInorder!=rootValue)
{
throw std::exception("Invalid put");
}
int leftLength=rootInorder-startInorder;
int rightLength=endInorder-rootInorder;
int* leftPreorderEnd=startPreorder+leftLength;
if(leftLength>0)
{
//递归构建左子树
root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
}
if(rightLength>0)
{
//递归构建右子树
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)
{
throw std::exception("Invalid put!");
}
return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}
void swrap_element(BinaryTreeNode** left,BinaryTreeNode** right)
{
BinaryTreeNode* temp=*left;
*left=*right;
*right=temp;
}
void MirrorRecursively(BinaryTreeNode* pNode)
{
if(pNode==NULL||(pNode->m_pLeft==NULL&&pNode->m_pRight))
return;
swrap_element(&pNode->m_pLeft,&pNode->m_pRight);
if(pNode->m_pLeft!=NULL)
MirrorRecursively(pNode->m_pLeft);
if(pNode->m_pRight!=NULL)
MirrorRecursively(pNode->m_pRight);
}
void PrintTreeNode(BinaryTreeNode* pNode) {
if(pNode != NULL)
{
printf("value of this node is: %d\n", pNode->m_nValue);
if(pNode->m_pLeft != NULL)
printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
else
printf("left child is null.\n");
if(pNode->m_pRight != NULL)
printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
else
printf("right child is null.\n");
}
else
{
printf("this node is null.\n");
}
printf("\n");
} //递归打印左右子树
void PrintTree(BinaryTreeNode* pRoot)
{
PrintTreeNode(pRoot);
if(pRoot != NULL)
{
if(pRoot->m_pLeft != NULL)
PrintTree(pRoot->m_pLeft);
if(pRoot->m_pRight != NULL)
PrintTree(pRoot->m_pRight);
}
}
//递归删除左右子树 void DestroyTree(BinaryTreeNode* pRoot)
{
if(pRoot != NULL)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight;
delete pRoot;
pRoot = NULL;
DestroyTree(pLeft);
DestroyTree(pRight);
}
} void main()
{
const int length1 = 8; int preorder1[length1] = {1, 2, 4, 7, 3, 5, 6, 8};
int inorder1[length1] = {4, 7, 2, 1, 5, 3, 8, 6}; BinaryTreeNode *root1 = Construct(preorder1, inorder1, length1); PrintTree(root1);
MirrorRecursively(root1);
PrintTree(root1); }
Java代码:
public class MirrorRecursively {
public static class BinaryTreeNode{
int m_nValue;
BinaryTreeNode m_pLeft;
BinaryTreeNode m_pRight;
}
public static BinaryTreeNode ConstructBiTree(int[] preOrder,int start,int[] inOrder,int end,int length){
if(preOrder==null||inOrder==null||preOrder.length!=inOrder.length||length<=0)
return null;
int value=preOrder[start];
BinaryTreeNode root=new BinaryTreeNode();
root.m_nValue=value;
root.m_pLeft=root.m_pRight=null;
//当整棵树只有一个节点的情况
if(length==1){
if(value==inOrder[end])
return root;
else
throw new RuntimeException("inVaild put");
}
//在中序遍历的数组中找到根节点
int i=0;
while(i<length){
if(value==inOrder[end-i]){
break;
}
i++;
}
if(i==length)
throw new RuntimeException("inVaild put!");
root.m_pLeft=ConstructBiTree(preOrder,start+1,inOrder,end-i-1,length-i-1);
root.m_pRight=ConstructBiTree(preOrder,start+length-i,inOrder,end,i);
return root;
}
public static void printNode(BinaryTreeNode pNode){
if(pNode==null)
return;
System.out.println("the node is:"+pNode.m_nValue);
if(pNode.m_pLeft!=null)
System.out.println("the left node is:"+pNode.m_pLeft.m_nValue);
else
System.out.println("the left node is null");
if(pNode.m_pRight!=null)
System.out.println("the right node is:"+pNode.m_pRight.m_nValue);
else
System.out.println("the right node is null");
}
public static void printBiTree(BinaryTreeNode pNode){
printNode(pNode);
if(pNode.m_pLeft!=null)
printBiTree(pNode.m_pLeft);
if(pNode.m_pRight!=null)
printBiTree(pNode.m_pRight);
}
//二叉树的镜像
public static void MirrorRecursive(BinaryTreeNode pHead){
if(pHead==null||(pHead.m_pLeft==null&&pHead.m_pRight==null))
return;
BinaryTreeNode pTemp=pHead.m_pLeft;
pHead.m_pLeft=pHead.m_pRight;
pHead.m_pRight=pTemp;
if(pHead.m_pLeft!=null)
MirrorRecursive(pHead.m_pLeft);
if(pHead.m_pRight!=null)
MirrorRecursive(pHead.m_pRight);
}
public static void main(String[] args){
int[] preOrder={3,6};
int[] inOrder={6,3};
BinaryTreeNode pNode=ConstructBiTree(preOrder,0,inOrder,1,preOrder.length);
printBiTree(pNode);
MirrorRecursive(pNode);
printBiTree(pNode);
}
}
剑指offer-第四章解决面试题的思路(二叉树的镜像)的更多相关文章
- 剑指offer第四章
剑指offer第四章 1.二叉树的镜像 二叉树的镜像:输入一个二叉树,输出它的镜像 分析:求树的镜像过程其实就是在遍历树的同时,交换非叶结点的左右子结点. 求镜像的过程:先前序遍历这棵树的每个结点,如 ...
- 剑指offer编程题Java实现——面试题6重建二叉树
题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2, ...
- 剑指offer-第四章解决面试题的思路(从上往下打印二叉树)
题目:从上往下打印二叉树的每一个节点,同一层的节点按照从左到右的顺序打印 思路:这是一个层序遍历的问题,因此要借用到队列.我们可以在打印第一个节点的同时将这个节点的左右子节点都放入队列,同样打印左右子 ...
- 剑指offer-第四章解决面试题的思路(栈的压入和弹出序列)
题目:输入两个整数序列,第一个序列表示栈的压入序列,请判断第二个序列是否为弹出序列. 思路:定义两个指针sPush和sPop分别指向两个整数序列的开头,借助一个辅助的栈,将第一个序列的数据依次压入栈中 ...
- 剑指offer-第四章解决面试题的思路(包含min函数的栈)
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数,在该栈中,调用min,push及pop的时间复杂度都是O(1) 思路:定义两个栈分别为dataStack和minStack ...
- 剑指offer-第四章解决面试题的思路(顺序打印矩阵)
题目:输入一个矩阵,按照从外向里的顺序依次打印出每一个数.(画图让抽象的问题形象化) 思路:打印矩阵时,把每一层当做一个圈来打印,找到打印整个矩阵的截止条件. 从上图中我可以看到一个6*6的矩阵(长宽 ...
- 剑指offer第五章
剑指offer第五章 1.数组中出现次数超过一半的数 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组 ...
- 剑指offer第七章&第八章
剑指offer第七章&第八章 1.把字符串转换成整数 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 输入描述: 输入一个字符串 ...
- 剑指offer第六章
剑指offer第六章 1.数字在排序数组中出现的次数 统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在数组中出现了4次,所以输出4 分析:思路1 ...
随机推荐
- ORM实例介绍
http://blog.csdn.net/RonoTian/article/details/2900714
- HTML5侧滑聊天面板
在线演示 本地下载
- Git常用分支操作
新建分支 git branch branchname 切换到分支dev git checkout branchname 查看所有的分支信息 git branch -a 查看远程分支信息 git bra ...
- 【bzoj3298】[USACO 2011Open]cow checkers(博弈论)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3298 博弈论经典结论题,我也没什么好说的.matrix67大佬比我想得深入的多:捡石子 ...
- Hibernate -- 配置c3p0连接池, 事务隔离级别, 管理session
知识点1:配置c3p0连接池(了解) * 引入c3p0-0.9.1.jar * 在hibernate.cfg.xml文件中增加如下配置 <!-- C3P0连接池设定--> <!-- ...
- OpenStack Ceilometer -- 后台数据存储优化之MongoDB的分片存储设置
https://xiaofandh12.github.io/Mongo-Shard 关于MongoDB MongoDB中的概念与关系型数据库之间的对应: Database --> Databas ...
- nrm npm源管理利器
nrm npm源管理利器 nrm是管理npm源的一个利器. 有时候我们用npm install 安装依赖时会非常的慢,是官方自身的npm本来就慢,然后我们会尝试安装淘宝的npm或者cnpm,这些安装切 ...
- Ajax基础(三)--eval的使用
eval的使用: 1.定义和用法 计算某个字符串,并执行其中的js代码 eval(string) string必须,含有表达式或执行语句 string有返回值的话 2.实例 2.1 字符串上该用eva ...
- Docker 应用实例
Docker安装Nginx 方法一.通过 Dockerfile构建 创建Dockerfile 首先,创建目录nginx,用于存放后面的相关东西. runoob@runoob:~$ mkdir -p ~ ...
- IOS-第三方(SDWebImage)
SDWebImage ReadMe.md 文档 附:SDWebImage框架github下载地址:https://github.com/rs/SDWebImage注1:该文章简单翻译了SDWebIma ...