二叉树树的算法题目

一、二叉树中用递归实现的各种题目总结

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);
}   
    原文作者:maoloveyu_ecstc
    原文地址: https://blog.csdn.net/maoloveyu_ecstc/article/details/75034536
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞