剑指offer
Posted cherry-bail
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer相关的知识,希望对你有一定的参考价值。
##本期 判断树的子结构 && 树的镜像
#题目 判断树的子结构
给两个二叉树,判断后一颗是否是前一颗的子树
方法:判断二叉树的树根和子树的树根是否相同,
若相同则继续判断左右孩子;
若不相同则二叉树的左右孩子作为树根继续做出上述的比较。
public boolean hasSubTree(treeNode root1, TreeNode root2){
if(root1 == null || root2 == null) return false;
return isSubTree(root1, root2) || hasSubTree(root1.leftchild, root2) || hasSubTree(root1.rightchild, root2);
}
public boolean isSubTree(TreeNode root1, TreeNode root2){
if(root2 == null) return true;
if(root1 == null) return false;
if(root1.val == root2.val){
return(isSubTree(root1.leftchild, root2.leftchild) && isSubTree(root1.rightchild, root2.rightchild));
}else{
return false;
}
}
题目 操作给定的二叉树,将其变换为源二叉树的镜像
源二叉树 8 镜像二叉树 8
/ /
6 10 10 6
/ / / /
5 7 9 11 11 9 7 5
如上图中的两颗树结构看出,镜像就是反转了所有节点的左右孩子。
那我们可以有递归和非递归的方式,将所有树节点的左右孩子交换
#递归
public void mirrorTrans(TreeNode root){
if(root == null) return;
if(root.leftchild = null && root.rightchild == null) return;
TreeNode temp = root.leftchild;
root.leftchild = root.rightchild;
root.rightchild = temp;
if(root.leftchild != null) mirrorTrans(root.leftchild);
if(root.rightchild != null) mirrorTrans(root.rightchild);
}
#前序遍历
前序遍历的顺序是根左右,我们按照顺序将所有左节点的左右孩子交换位置,依次压栈,出栈的时候将所有右节点的左右孩子交换位置
public void pre(TreeNode root){
if(root == null) return;
Stack nstack;
TreeNode temp;
while(root != null || nstack.empty() != true){
while(root != null){
if(root.leftchild != null && root.rightchild != null){
TreeNode temp = root.leftchild;
root.leftchild = root.rightchild;
root.rightchild = temp;
}
nstack.push(root);
root = root.leftchild;
}
while(nstack.empty() != true){
root = nstack.top;
nstack.pop();
root = root.rightchild;
}
}
}
public void preBFS(TreeNode root){
if(root == null) return;
Stack nstack;
TreeNode temp;
nstack.push(root);
while(nstack.empty() != true){
root = nstack.top;
nstack.pop();
}
if(root.leftchild != null && root.rightchild != null){
TreeNode temp = root.leftchild;
root.leftchild = root.rightchild;
root.rightchild = temp;
}
if(root.leftchild != null){
nstack.push(root.leftchild);
}
if(root.rightchild != null){
nstack.push(root.rightchild);
}
}
}
#中序遍历
中序遍历的顺序是左根右
由于遍历左节点后,
public void mid(TreeNode root){
if(root == null) return;
Stack nstack;
TreeNode temp;
while(root != null || nstack.empty() != true){
while(root != null){
nstack.push(root);
root = root.leftchild;
}
if(nstack.empty() != true){
root = nstack.top;
if(root.leftchild != null && root.rightchild != null){
TreeNode temp = root.leftchild;
root.leftchild = root.rightchild;
root.rightchild = temp;
}
nstack.pop();
root = root.leftchild;
}
}
}
#后序遍历
后续遍历的顺序是左右根,同先序遍历
public void post(TreeNode root){
if(root == null) return;
TreeNode cur; //当前节点
TreeNode pre == null; //前一次访问的节点
nstack.push(root);
while(nstack.empty( ) != true){
cur = nstack.top;
if((cur.leftchild == null || cur.rightchild == null) || (pre != null &&(pre == cur.leftchild || pre == cur.rightchild))){
//如果当前结点没有孩子结点或者孩子节点都已被访问过
// 将原来的输出改为交换左右子树即可
if(cur.leftchild != null && cur.rightchild != null){
TreeNode temp = root.leftchild;
root.leftchild = root.rightchild;
root.rightchild = temp;
}
nstack.pop();
pre = cur;
}else{
// 由于栈是先进后出,因此先入右孩子, 再左孩子可以保证递归返回时先遍历左孩子
if(cur.rightchild != NULL){
nstack.push(cur.rightchild);
}
if(cur.leftchild != NULL){
nstack.push(cur.leftchild);
}
}
}
}
以上是关于剑指offer的主要内容,如果未能解决你的问题,请参考以下文章
剑指 Offer 45. 把数组排成最小的数 剑指 Offer 61. 扑克牌中的顺子 剑指 Offer 40. 最小的k个数
剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)
剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)