剑指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 ...
随机推荐
- Linux系统中使用netcat命令的奇技淫巧
netcat是网络工具中的瑞士军刀,它能通过TCP和UDP在网络中读写数据.通过与其他工具结合和重定向,你可以在脚本中以多种方式使用它.使用netcat命令所能完成的事情令人惊讶. netcat所做的 ...
- IDEA 编译时 未结束的字符串文字
这个问题就是编码的问题,修改文件的编码可以解决 1. IDEA中 file-->Settings 找到File Encodings,将IDE Encoding.Project Encodin ...
- Pyspider爬虫教程
Pyspider爬虫教程 一.安装 1. 安装pip (1)准备工作 yum install –y make gcc-c++ python-devel libxml2-devel libxslt-de ...
- 因为swap分区无法启动
用户启动时停在如下截图
- 嵌套的SQL另外一种写法
SELECT a.TradeOrderID 二段交易号 , c.TradeOrderID 一段订单号 , a.BaggingDate AS 出库时间 , a.TransportOrderCode AS ...
- NumPy数学算数函数
NumPy - 算数函数 很容易理解的是,NumPy 包含大量的各种数学运算功能. NumPy 提供标准的三角函数,算术运算的函数,复数处理函数等. 三角函数 NumPy 拥有标准的三角函数,它为弧度 ...
- windows8.1下安装Cygwin并通过apt-cyg安装软件包
参考 http://yuanshuilee.blog.163.com/blog/static/2176972752014126786185/ http://www.cnblogs.com/zhang- ...
- Django进阶Model篇003 - 数据库同步技巧
一.认识一个目录 目录名:migrations 作用:用来存放通过makemigrations命令生成的数据库脚本,不熟悉的情况下,里面生成的脚本不要轻易修改.app目录下必须要有migrations ...
- HDU 3037 组合数、lucas,逆元
题目链接 题目大意,N颗树上取不超过M个果子,求总方案个数模P的值,P是质数且不超过10w,N,M不超过1e9: 在这里树是被认为不同的,也就是将k(0<=k<=M)个小球放入N个不同的盒 ...
- day5-time & datetime模块
1.概述 程序设计开发过程中,往往存在很多场景,需要把时间和日期以某种特定形式格式化输出,在python中我们需要借助time & datetime模块来实现,今天就来一探这两大模块的究竟. ...