二叉树树的算法题目

来源:互联网 发布:js中的map的使用 编辑:程序博客网 时间:2024/05/29 04:49

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

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);}