二叉树的进阶面试题

package com.wschase.binarytree;

import java.util.*;

/**二叉树的进阶面试题
 * Author:WSChase
 * Created:2019/4/10
 */
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
public class Solution {
    /**
     * 1.二叉树的前序遍历——非递归实现
     */
//    public List<Integer> preorderTraversal(TreeNode root) {
//        //二叉树的前序遍历的非递归实现:
//        //我们用一个栈来存放我们遍历的结点,然后通过查看访问结点的次数就可以知道前序遍历的结果
//        Stack<TreeNode> s=new Stack<>();
//        List<Integer> list=new ArrayList<>();
//        //我们进行遍历时的当前结点
//        TreeNode cur=root;
//        //当前栈顶的结点
//        TreeNode top=null;
//
//        while(cur!=null||!s.empty()){
//            //实现一路向左把结点放进栈里面
//            while(cur!=null){
//                list.add(cur.val);
//                s.push(cur);
//                cur=cur.left;
//            }
//            top=s.peek();
//            s.pop();
//            cur=top.right;
//        }
//        return list;
//    }
    /**
     * 2.二叉树的中序遍历——非递归实现
     */
//    public List<Integer> inorderTraversal(TreeNode root) {
//        //二叉树的前序遍历的非递归实现:
//        //我们用一个栈来存放我们遍历的结点,然后通过查看访问结点的次数就可以知道前序遍历的结果
//        Stack<TreeNode> s=new Stack<>();
//        List<Integer> list=new ArrayList<>();
//        //我们进行遍历时的当前结点
//        TreeNode cur=root;
//        //当前栈顶的结点
//        TreeNode top=null;
//
//        while(cur!=null||!s.empty()){
//            //实现一路向左把结点放进栈里面
//            while(cur!=null){
//                s.push(cur);
//                cur=cur.left;
//            }
//
//            //这个地方表示第二次遇到这个结点
//            top=s.peek();
//            list.add(top.val);
//            s.pop();
//            cur=top.right;
//        }
//        return list;
//    }

    /**
     * 3.二叉树的后序遍历——非递归实现
     */
//    public List<Integer> postorderTraversal(TreeNode root) {
//        Stack<TreeNode> s=new Stack<>();
//        List<Integer> list=new ArrayList<>();
//        TreeNode cur=root;
//        TreeNode top=null;
//        TreeNode last=null;
//        while(cur!=null||!s.empty()){
//            //第一次遇到这个结点
//            while (cur!=null){
//                //一路向左的过程
//                s.push(cur);
//                cur=cur.left;
//            }
//            //一定是向左遇到null以后,利用栈处理剩余的右子树
//            top=s.peek();
//            if(top.right==null){
//                list.add(top.val);
//                s.pop();
//                //上一个被遍历过三次的结点
//                last=top;
//            }else {
//                cur=top.right;
//            }
//        }
//        return list;
//    }

    /**
     * 4.
     */


    /**
     *5.二叉树的层序遍历
     */
//    public List<List<Integer>> levelOrder(TreeNode root) {
//        //这个层序遍历返回的结果是一个List集合,但是这个结合比较特殊,因为最后需要的是一个二维数组
//        //就是在List集合里面存放的还是List集合。
//
//        //(1)根节点为空
//        if(root==null){
//            //返回一个空的顺序表
//            return new ArrayList<>();
//        }
//
//        //我们需要一个队列来实现中间的转化关系:就是将一颗二叉树首先放进一个队列里面,然后取出来放进集合里面
//        Queue<TreeNode> queue=new LinkedList<>();
//
//        //再定义一个集合来存放返回的结果
//        List<List<Integer>> result=new ArrayList<>();
//
//        //根节点不为空的情况
//        queue.add(root);
//
//
//        while (!queue.isEmpty()){
//            //用于计数队列里面还有几个数
//            int count= queue.size();
//            List<Integer> list=new ArrayList<>();
//            while (count>0){
//
//                //(1)将根节点放进集合里面了
//          TreeNode top=queue.peek();
//          queue.poll();
//          list.add(top.val);
//
//          //再判断它的左子树
//                if(top.left!=null){
//                 queue.add(top.left);
//                }
//
//                //再判断右子树
//                if(top.right!=null){
//                 queue.add(top.right);
//                }
//                count--;
//            }
//
//            //如果跳出了上面的循环以后就结束了遍历整个二叉树,此时将这个集合放进一个集合里面
//            //这个result就是一个二位的数组——二维顺序表
//            result.add(list);
//        }
//        return result;
//    }

    /**
     * 6.给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
     *
     * 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
     *
     * 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]
     * 示例 1:
     *
     * 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
     * 输出: 3
     * 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
     */
    /**
     判断最近公共祖先结点的思路:
     我们首先这两个结点是否在同一棵树上面,如果不在那么它们的最近祖先结点就是根节点;
     如果同时在左子树,那么再去左子树判断,直到根节点为null的时候才终止判断;
     如果同时在右子树,那么就去右子树判断,这个过程就是递归的过程。
     */
//    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//        if(root==null){
//            return root;
//        }
//        if(p==root||q==root){
//            return root;
//        }
//        TreeNode left=lowestCommonAncestor(root.left,p,q);
//        TreeNode right=lowestCommonAncestor(root.right,p,q);
//
//        //这个表示这两个结点一个在根节点的左子树、一个在根节点的右子树——最近公共祖先结点就是根节点
//        if(left!=null&&right!=null){
//            return root;
//        }
//        if(left!=null){
//            return left;
//        }
//        if(right!=null){
//            return right;
//        }
//        return null;
//    }

    /**
     * 7.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
     * 要求不能创建任何新的结点,只能调整树中结点指针的指向。
     */
    /**
     public class TreeNode {
     int val = 0;
     TreeNode left = null;
     TreeNode right = null;

     public TreeNode(int val) {
     this.val = val;

     }
     }
     */
    /**
     * 在根节点(当前值)的前面访问的是左子树,那么一个结点的左子树就是它的前驱结点;
     * 一个结点的右子树是在它访问之后访问的,所以它的右孩子作为它的后继,这样就构成了
     * 双向链表。由于中序遍历的顺序本来就是:左子树——根节点——右子树,所以我们只需要修改左子树就可以
     * 实现双向链表。
     * @param root
     * @return
     */
//    public TreeNode Convert(TreeNode root) {
//            if (root == null)
//                return null;
//            Stack<TreeNode> stack = new Stack<>();
//            TreeNode p = root;
//            TreeNode pre = null;// 用于保存中序遍历序列的上的节点
//        //是否是第一次遍历这个结点
//            boolean isFirst = true;
//            while (p != null || !stack.isEmpty()) {
//                while (p != null) {
//                    stack.push(p);
//                    p = p.left;
//                }
//                p = stack.pop();
//                if (isFirst) {
//                    //在中序遍历中的第一次遍历的结点为双向链表的前驱
//                    root = p;// 将中序遍历序列中的第一个节点记为root
//                    pre = root;
//                    isFirst = false;
//                } else {
//                    //这个地方表示第二次遇到这个结点
//                    pre.right = p;//这个pre.right就相当于是pre.next
//                    p.left = pre;
//                    pre = p;
//                }
//                p = p.right;
//            }
//
//            //通过root可以找到这个链表
//            return root;
//        }

    /**
     * 8.根据一棵树的前序遍历与中序遍历构造二叉树。
     * 注意:
     * 你可以假设树中没有重复的元素。
     * 例如,给出
     * 前序遍历 preorder = [3,9,20,15,7]
     * 中序遍历 inorder = [9,3,15,20,7]
     * 返回如下的二叉树:
     *     3
     *    / \
     *   9  20
     *     /  \
     *    15   7
     */
//    public TreeNode build(int[] preorder,int[] inorder,int startPre,int endPre,int startIn,int endIn){
//        if(startPre>endPre){
//            return null;
//        }
//        if(startPre==endPre){
//            return new TreeNode(preorder[startPre]);
//        }
//        int rootval=preorder[startPre];
//        TreeNode root=new TreeNode(rootval);
//        //在中序遍历里面找到属于二叉树的左子树和右子树的结点
//        for(int i=startIn;i<=endIn;i++){
//            if(inorder[i]==rootval){
//                root.left=build(preorder,inorder,startPre+1,startPre+i-startIn,startIn,i-1);
//                root.right=build(preorder,inorder,startPre+i-startIn+1,endPre,i+1,endIn);
//                break;
//            }
//        }
//        return root;
//    }
//    public TreeNode buildTree(int[] preorder, int[] inorder) {
//
//        return build(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1);
//
//    }


        /**
         * 9.根据一棵树的中序遍历与后序遍历构造二叉树。
         * 注意:
         * 你可以假设树中没有重复的元素。
         * 例如,给出
         * 中序遍历 inorder = [9,3,15,20,7]
         * 后序遍历 postorder = [9,15,7,20,3]
         * 返回如下的二叉树:
         *
         *     3
         *    / \
         *   9  20
         *     /  \
         *    15   7
         */
//    public TreeNode buildTree(int[] inorder, int[] postorder) {
//        return realTree(inorder,0,inorder.length,postorder,0,postorder.length);
//    }
//
//    public TreeNode realTree(int[] inorder,int a,int b,int[] postorder,int c,int d){
//        if(a==b || c==d)
//            return null;
//        TreeNode node=new TreeNode(postorder[d-1]);
//        for(int i=a;i<b;i++){
//            if(inorder[i]==postorder[d-1]){
//                node.left=realTree(inorder,a,i,postorder,c,i+c-a);
//                node.right=realTree(inorder,i+1,b,postorder,i+c-a,d-1);
//                break;
//            }
//        }
//        return node;
//    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值