编程题——二叉树

题目:

1. 已知前序和中序,重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
2. 判断二叉树B是不是A的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
3、源二叉树的镜像(前序,有孩子节点就交换)
操作给定的二叉树,将其变换为源二叉树的镜像。
4、按层打印二叉树(队列)
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
5、判断数组是不是某二叉搜索树的后序遍历的结果(判断左右子树和根节点大小关系)
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
6、打印出二叉树中结点值的和为输入整数的所有路径(前序遍历,ArrayList存放路径,和路径集合)
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

————————————————————————————————————————————————

代码如下:
1. 已知前序和中序,重建二叉树
/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution 
{
    public TreeNode reConstructBinaryTree(int [] pre,int [] in)
    {
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,
                                             in,0,in.length-1);
        return root;
    }

    private TreeNode reConstructBinaryTree(int[]pre,int preL,int preR,
                                           int[]in,int InL,int InR)
    {
        if(preL>preR||InL>InR)
            return null;

        //从前序遍历序列  找到要构建的二叉树的根节点root
        TreeNode root=new TreeNode(pre[preL]);//构建二叉树,根节点初始化为 前序遍历第一个节点
        int leftTreeSize=0;//定义前序遍历根节点 在中序遍历中 位置 左边的左子树的长度

        //遍历中序数组
        for (int i = InL; i <=InR ; i++)
        {
            if(in[i]==pre[preL])//一直遍历中序数组,直到找到与前序数组中的根节点相等的节点,此时根节点在中序数组中下标为i
            {
                leftTreeSize=i-InL;//找到与前序遍历对应的根节点所在的 下标i 时,在中序遍历数组中根节点左边左子树的长度

                //第一次找到二叉树左子树 ,pre :[preL,[preL+1,,,,preL+leftTreeSize],[preL+leftTreeSize+1,,,,preR]]对应 根左右
                //左子树在  前序遍历和中序遍历的 对应区间
                root.left=reConstructBinaryTree(pre,preL+1,preL+leftTreeSize,
                                                in,InL,i-1);
                //第一次找到二叉树右子树,In,[[InL,,,i-1],i(根节点所在下标),[i+1,inR]]对应 左根右
                //右子树在 前序遍历  和  中序遍历的 对应区间 
                root.right=reConstructBinaryTree(pre,preL+leftTreeSize+1,preR,
                                                 in,i+1,InR);
                break;
            }
        }

        return root;

    }
}

2. 判断二叉树B是不是A的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

public class Solution {
     public boolean HasSubtree(TreeNode root1,TreeNode root2)
    {
         if(root1==null||root2==null)
             return false;
         //如果找到了对应Tree2的根节点的点
          //如果找不到,那么就再去root的左儿子当作起点,去判断时候包含Tree2
          //如果还找不到,那么就再去root的右儿子当作起点,去判断时候包含Tree2
         return doesTree1HaveTree2(root1,root2)||
             HasSubtree(root1.left,root2)||
             HasSubtree(root1.right,root2);
  /**************************************************/       
    /*    boolean res=false;
        if(root2!=null && root1!=null) //当Tree1和Tree2都不为零的时候,才进行比较。否则直接返回false
        {
            //如果找到了对应Tree2的根节点的点
            if(root1.val==root2.val)
                res=doesTree1HaveTree2(root1,root2); //以这个根节点为为起点判断是否包含Tree2

            //如果找不到,那么就再去root的左儿子当作起点,去判断时候包含Tree2
            if(!res)
                res=HasSubtree(root1.left,root2);

            //如果还找不到,那么就再去root的右儿子当作起点,去判断时候包含Tree2
            if(!res)
                res=HasSubtree(root1.right,root2);

        }
        return res;
        */
/***********************************************************/
    }

    private  boolean doesTree1HaveTree2(TreeNode node1,TreeNode node2)
    {
         if (node1 == null && node2 == null) 
             return true;

        //如果Tree2还没有遍历完,Tree1却遍历完了。返回false
        if(node1==null&&node2!=null)
            return false;

        //如果Tree2已经遍历完了都能对应的上,返回true(不管1树有没有遍历完)
        if(node2==null)
            return true;

        //如果其中有一个点没有对应上,返回false
        if(node1.val!=node2.val)
            return false;

        //如果根节点对应的上,那么就分别去子节点里面匹配
        return doesTree1HaveTree2(node1.left,node2.left)
                &&doesTree1HaveTree2(node1.right,node2.right);

    }
}
3、源二叉树的镜像

操作给定的二叉树,将其变换为源二叉树的镜像。

public class Solution{
/*    //非递归:这里的非递归方式使用的储存结构可以是栈也可以是队列,因为交换顺序和出栈出队列顺序无关
    public void Mirror(TreeNode root){

        if(root==null)
            return;

        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        while(!stack.empty())
        {
            TreeNode tree=stack.pop();

            if(tree.left!=null||tree.right!=null)
                swap(tree);

            if(tree.left!=null)
                stack.push(tree.left);

            if(tree.right!=null)
                stack.push(tree.right);
        }

    }*/

    //递归方法
     /**
     * 递归:前序遍历,如果遍历到的节点有孩子,就交换它的两个子节点
     * 当交换完所有的非叶子结点的左右子结点之后,就得到了树的镜像
     */
    public void Mirror(TreeNode root)
    {
        if(root==null)//根节点为空
            return;
        if(root.left==null&&root.right==null)//只有根节点
            return;

        //交换节点的左右孩子节点
        swap(root);

        //递归左右孩子的孩子节点
        Mirror(root.left);
        Mirror(root.right);
    }

    private void swap(TreeNode root)
    {
        TreeNode tempNode=root.left;
        root.left=root.right;
        root.right=tempNode;
    }
}

4、按层打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印。

public class Solution {
    //队列思想,按层遍历二叉树
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root)
    {
        ArrayList<Integer>res=new ArrayList<>();
        if(root==null)
            return res;
        Queue<TreeNode>queue=new LinkedList<>();
        queue.add(root);

        while(!queue.isEmpty()){
            TreeNode node=queue.poll();//将队列中的节点弹出
            res.add(node.val); //加入集合

            if(node.left!=null)
                queue.offer(node.left);//将节点左孩子入队

            if(node.right!=null)
                queue.offer(node.right);//将节点右孩子入队
        }
        return res;
    }
}
5、判断数组是不是某二叉搜索树的 后序遍历 的结果

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

//思想:先判断左右孩子,再递归左右子树;关键是找到左子树的长度下标leftIndex,判断和根节点大小关系
//5 7 6  9 11 40   8 
public class Solution
{
    public boolean VerifySquenceOfBST(int [] sequence)
    {
      if(sequence==null||sequence.length==0)
          return false;
      return verify(sequence,0,sequence.length-1);
    }


    private boolean verify(int[]sequence,int first,int last)
    {
        if(last-first<=1)
            return true;

        int root=sequence[last];//根节点
        int leftIndex=first;

        //在二叉搜索树中  左子树的结点 < 根节点,
        while(leftIndex<last&&sequence[leftIndex]<=root)
            leftIndex++;//左子树个数

        //在二叉搜索树中  右子树的结点 > 根节点,
        for (int i = leftIndex; i <last ; i++) {
            if(sequence[i]<root)
                return false;
        }
        //判断左右子树是不是二叉搜索树 
        //5 7 6  9 11 40   8     leftIndex=3指向9
        return verify(sequence,first,leftIndex-1)&&
               verify(sequence,leftIndex,last-1);
    }
}
6、打印出二叉树中 节点值的和为target 的所有路径

输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

/**
 * E remove(int index)
         移除此列表中指定位置上的元素。
   boolean remove(Object o)
         移除此列表中首次出现的指定元素(如果存在)。
 */

 //思想:从根节点开始,则前序遍历,先add根节点,在findPath左右孩子;存放路径ArrayList

public class Solution {
     //放外面,防止递归时候,清除掉res集合中路径
    ArrayList<ArrayList<Integer>>res=new ArrayList<>();//存路径的集合
    ArrayList<Integer>al=new ArrayList<>();//存路径

    public ArrayList<ArrayList<Integer>>FindPath(TreeNode root,int target){
        if(root==null)
            return res;       
        al.add(root.val);
        target-=root.val;

        //和满足,并且是到达叶子结点了
        if(target==0&&root.left==null&&root.right==null)
        {
            res.add(new ArrayList<>(al));//不重新new的话从始至终listAll中所有引用都指向了同一个一个list
        }
        else if(target>0)//当target<0时,已经没必要继续向下深度遍历了,增加这个判断可以节省不必要的开销。
        {
            if(root.left!=null)
                FindPath(root.left,target);

            if(root.right!=null)
                FindPath(root.right,target);
        }
        //递归到叶子节点如果还没有找到满足和值的路径,就要回退到父节点继续寻找,依次类推
        // 即使满足了也会回退,寻找另外路径

        al.remove(al.size()-1);//E remove(int index)移除此列表中指定位置上的元素。

        return res;

         /* 为什么remove了, 不需要 target-root.val,因为递归到最后返回时,target又会自动恢复到上一层的值。
        另外,target又没有作为返回值,你加上去了也没用。*/
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值