一、二叉树中用递归实现的各种题目总结
1.将一棵二叉树转化成双向链表
二叉树转化成双向链表的过程,就是中序遍历的过程。问题的关键是如何将在遍历二叉树的同时,修改指针指向,满足双向要求。
public TreeNode Convert(TreeNode root) {
if(root==null)return null;
if(root.left==null&&root.right==null)return root;
TreeNode left=Convert(root.left);
TreeNode p=left;
while(p!=null&&p.right!=null)//左子树的最大值---最右值
{
p=p.right;
}
if(left!=null)
{
p.right=root;
root.left=p;
}
TreeNode right=Convert(root.right);//root结点的右子树
if(right!=null)
{
root.right=right;
right.left=root;
}
return left!=null?left:root;
}
2.重建二叉树
给定按照前序遍历得出的顺序数组和按照中序遍历得出的顺序数组,重新构建二叉树。
public TreeNode traversTree(int[] pre,int[] in){
return tranversTree(pre,0,pre.length-1,in,0,in.length-1);
}
public TreeNode traversTree(int[] pre,int pStr,int pEnd,int[] in,int iStr,int iEnd){
if(pStr>pEnd || iStr>iEnd) return null;
TreeNode root=new TreeNode(pre[pStr]);
for(int i=iStr;i<=iEnd;i++){
if(pre[pStr]==in[i]){
root.left=traversTree(pre,pStr+1,i-iStr+pStr,in,iStr,i-1);
root.right=traversTree(pre,i-iStr+pStr+1,pEnd,in,i+1,iEnd);
}
}
return root;
}
、
3.判断输入两棵树A,B,A树是否为B的子结构
过程:①首先判断A树的头结点和B树的头结点是否相同,如果相同,那么就比A的左右孩子和B的左右孩子是否相同
②如果不同,那么就需要比较A的左孩子和B树是否相同或者A的右孩子和B树是否相同
public boolean hasTree(TreeNode A,TreeNode B){
boolean result=false;
if(A!=null && B!=null){
if(A.val==B.val){
result=hasAInB(A,B);
}else{
if(!result &&B.left!=null) result=hasTree(A,B.left);
if(!result &&B.right!=null) result=hasTree(A,B.right);
}
}
return result;
}
public boolean hasAInB(TreeNode A,TreeNode B){
if(A==null) return true;
if(B==null) return false;
if(A.val!=B.val) return false;
return hasAInB(A.left,B.left) && hasAInB(A.right,B.right);
}
4.判断某二叉树是否为对称二叉树
过程:①其实就是比较A,B两个结点的左右孩子,
比较A结点的左孩子跟B结点的右孩子是否相等,A结点的右孩子和B结点的左孩子是否相等
public boolean isSym(TreeNode A){
if(A==null) return true;
else return f(A.left,A.right);
}
public boolean f(TreeNode left,TreeNode right){
if(left==null && right==null) return true;
else if(left!=null && right!=null) return left.val==right.val && f(left.left,right.right) && f(left.right,right.left);
else return false;
}
5.某二叉树中和为某一个固定值的路径
从根结点出发,遍历所有的结点,直到满足跟目标值相同时,输出打印
public void find(TreeNode root,int target){
if(root==null) return;
Stack stack=new Stack();
findPath(root,target,0,stack);
}
public void findPath(TreeNode root,int expect,int cur,Stack stack){
cur+=root.val;
stack.push(root.val);
boolean isLeaf=root.left==null && root.right==null;
if(cur==expect&&isLeaf){
}
if(root.left!=null) findPath(root.left,expect,cur,stack);
if(root.right!=null) findPath(root.right,expect,cur,stack);
stack.pop();
}
6.两棵树的公共祖先
分三种情况讨论,
如果结点中含有指向父结点的索引,那么就很简单,从结点出发指向头结点的路径中保存在数组或者栈中,最后找到两个数组中最先的相同结点即可
如果是线索二叉树的话,那么就需要判断两个结点的位置
1)如果两个结点小于头结点,公共祖先在左子树
2)如果两个结点比头结点大,那么公共祖先在右孩子
3)如果两个结点一大一小,那么公共祖先在头结点
如果就是普通二叉树,题目就转化成从根结点出发,做层次遍历或者顺序遍历,判断两个结点是否出现在根结点下,如果在返回true,如果不在返回false,返回当前节点的父结点即可满足要求。
方法二,找到从根结点到到输入结点的路径,然后将问题转化为求两个链表的最后公共结点即可。
Stack path=new Stack();
public boolean findPath(TreeNode root,int val){
if(root==null) return false;
path.push(root);
if(root.val==val) return true;
else{
boolean find=findPath(root.left,val);//从左子树中找
if(!find) findPath(root.right,val);//左子树找不到,从右子树中找
if(!find) path.pop();//如果从左右两棵树中均没有找到,那么就弹出
return find;
}
}
//从底而非头出发遍历整个堆栈,判断第一次找到最后的公共结点即可
public TreeNode getCommon(TreeNode tn1,TreeNode tn2){
int com=0;
for(int i=0;i<tn1.size();i++){
if(tn1.get(i).val==tn2.get(i).val){
continue;
}else{
com=i-1;
break;
}
}
if(com<0) return null;
else return tn1.get(com);
}