lee二叉树题目

前序遍历 加 中序遍历
求二叉树的样子。

在这里插入图片描述
树中
在这里插入图片描述
最重要的是在数组中找到左子树的下标范围和右子树的下标范围

我们需要在中序数组中,去找到根节点的下标
为了提高效率,我们可以把中序序列放进一个hash表里这样好找。查找效率很高。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    private HashMap<Integer,Integer> getindex = new HashMap<>();
    //用来存储中序遍历中的根节点位置
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length;
        //构造hash映射
        for(int i = 0;i < n;i++){
            getindex.put(inorder[i],i);//用值找下标

        }

        return MyBuildTree(preorder,0,n - 1,inorder,0,n - 1);



    }

    public TreeNode MyBuildTree(int[] preorder,int preLeft,int preRight,int[] inorder,int inordLeft,int inordeRight){


        if(preLeft > preRight){
            return null;//左右下标相等时候结束
        }

        //往往通过两棵树才能每次确定好应该传递的左右子树


        //先建立根节点,每颗子树都要去建立根节点
        TreeNode root = new TreeNode(preorder[preLeft]);
        //建立根节点之后根据递归可以得到自己的左子树
        //pre的左子树范围是
        //preLeft + 1到 index - inordLeft + preleft

        //右子树范围是
        //index - inordLeft + preleft + 1,preRight


        //inorder左子树范围是 inordleft,index - 1
        //右子树范围是 index + 1 ,inordRight
        int index = getindex.get(preorder[preLeft]);//从hash里拿到中序遍历的根节点
        //根据前序遍历的最左边的那个


        //这里是建立左子树,所以传递Pre和inorder的左子树
        root.left = MyBuildTree(preorder, preLeft + 1, index - inordLeft + preLeft, inorder, inordLeft, index - 1);

        //建立右子树,将两个右子树传递进去
       

        root.right = MyBuildTree(preorder,index - inordLeft + preLeft + 1,preRight,inorder,index + 1,inordeRight);

        return root;//每次建立完成都将根节点返回

    }
}

递归终止条件就是左下标小于右下标时候

相等的时候都需要循环。

每次都是向左递归建立左子树,
这时候将每个数组左子树都交给递归,建立之后返回根节点就行了
记住返回根节点就好
你每次递归的任务都是建立一个左子树和一个右子树,左子树和右子树交给别人去做,自己只负责建立根节点。

二叉树遍历:
深度优先,广度优先
在这里插入图片描述
二叉树深度优先遍历
当然你必须要写个循环,将所有没被访问过的节点都丢进去进行深度优先遍历

void dfs(TreeNode root) {
    if (root == null) {
        return;
    }
    dfs(root.left);
    dfs(root.right);
}


二叉树广度优先遍历

void bfs(TreeNode root) {
    Queue<TreeNode> queue = new ArrayDeque<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll(); // Java 的 pop 写作 poll()
        if (node.left != null) {
            queue.add(node.left);
        }
        if (node.right != null) {
            queue.add(node.right);
        }
    }
}


使用队列结构进行广度优先遍历。
但是广度优先遍历用作
层次遍历有个缺点。
在这里插入图片描述
就是你还没解决当前层的时候,
队列里同时会把下一层的也在进队。也就是输出时候当前队列里不仅有这层东西,还有别的层东西,所以我们最好清空整个队列,整个队列中当前层都被清空之后,再让别的层的东西输出。

加一for循环将当前前队列里已经有的节点都结束后再搞定别的节点

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        if (root == null) {
            return ret;
        }

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> level = new ArrayList<Integer>();
            int currentLevelSize = queue.size();
            for (int i = 1; i <= currentLevelSize; ++i) {
                TreeNode node = queue.poll();
                level.add(node.val);
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            ret.add(level);
        }
        
        return ret;
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/er-cha-shu-de-ceng-xu-bian-li-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

所以最终层序遍历的结果就是

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();

    Queue<TreeNode> queue = new ArrayDeque<>();
    if (root != null) {
        queue.add(root);
    }
    while (!queue.isEmpty()) {
        int n = queue.size();
        List<Integer> level = new ArrayList<>();
        for (int i = 0; i < n; i++) { 
            TreeNode node = queue.poll();
            level.add(node.val);
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        res.add(level);
    }

    return res;
}

在这里插入图片描述
这种就是,很简单真的
层序遍历每层都是左到右,存进一个list里面
这个它希望是一次左到右一次右到左
那我们还是层序遍历的玩法
只不过加一个标志位,标志这一行是左到右还是右到左
然后用一个linkedlIst
如果左到右,那么我们就是和层序遍历一样处理
Linkedlist.add()处理
如果右到左遍历,那不就是linkedlist.addfirst(加到头部就行。

二叉树深度题目

其实很简单,用递归就行了,每次进去时候
两个参数,一个是当前深度depth,另外一个是最大深度max
我们最终需要输出和返回的是最大深度Max
我们每次进去递归,都要清楚地记录当前深度和最大深度进行比较,看看谁比较大,如果有更大深度就更新更大深度,
然后进行左右递归,左右递归回来看看能不能更新最大深度,如果能更新,那么就更新最大深度后返回,如果不能更新,那么就返回当前的最大深度,我们永远返回的是最大深度
一进去的时候,也是包含了深度的,递归一开始treeNode也是有深度的,所以一开始深度为1.
这是第一个方法

我们还有第二个方法就是
层序遍历,就是bfs这个套路
用for去控制每一层节点都排除队列,然后将所有节点下一层放进来,每次层数加深我们就depth++一直到最后。

class Solution {
    public int maxDepth(TreeNode root) {

        if(root == null){
            return 0;
        }
        //直接递归统计深度

        int depth = 1;
        int maxDepth = 0;
        maxDepth = dfs(root,depth,maxDepth);

        return maxDepth;


    }

    public static int dfs(TreeNode root,int depth,int maxDepth){
        //深度优先遍历
        if(root == null){
            maxDepth = Math.max(depth,maxDepth);
            return maxDepth;
        }
        maxDepth = Math.max(depth,maxDepth);//时刻更新最大深度

        int leftDepth = maxDepth,rightDepth = maxDepth;
        if(root.left != null){
            leftDepth = dfs(root.left,depth + 1,maxDepth);
        }

        if(root.right != null){
            rightDepth = dfs(root.right,depth + 1,maxDepth);
        }

        maxDepth = Math.max(leftDepth,rightDepth);//对比一下左右两边拿个最深

        return maxDepth;




    }


}

在这里插入图片描述
求深度题目,不知道返回什么那么我们就设置一个全局变量好了
在这里插入图片描述
我需要知道我这个点左右子树最大深度是多少
left = dfs
right = dfs就行
dfs要返给我子树的最大深度
需要left 和right比价之后加1返回给我,因为路径 + 1嘛

那么我们可以倒着来
最后一个节点7,它的往下最大深度就是0
距离上面返回 + 1就是 1
11的最大深度就是1和 1进行比较11的最大深度就是1

4到底的最大深度就是2和 1进行比较
网上返回一个3给5
上层因此知道了自己层数
相当于最底层部门距离上层级别数
最底层部门到最底差0级,我就是最底层部门
领导想知道自己和最底层部门之间差多少级别,让底下人往上汇报
最底级别部门,距离底层差0级别,自己就是0级,汇报给更高一层部门层级就加1,更高一层部门距离最底层1级
更高部门继续往上汇报,在自己左右底层基础上对比,找到最底层是多少,然后汇报上去,继续加一层

在这里插入图片描述

在这里插入图片描述

递归往下找
当遇到我们找到了的时候
将这个节点root往上交交给上一层
告诉上一层我们找到了一个

如果一直到底层都没找到,只能告诉上一层,对不起,老大一个都没找到,返回的就是Null

在这里插入图片描述

在这里插入图片描述
红色的每一层返回的都是Null给上一层

在这里插入图片描述

就是这张著名的图
如果没一直到底,都没遇到要找到,那么就返回Null告诉上面自己一无所获得,只获得一个也可以,只要获得了一个就可以返回交差了。
每一个节点都要做的事情是,看看自己是不是Null或者pq?如果是,把自己交上去了
如果不是,那么你会得到左边一个部下的汇报,还有右边一个部下的汇报

最好的情况,左右都不为Null,说明你赚大发了,你就是第一人,你作为某个人的部下,把自己的大名报上去了就行,你一个人解决了所有问题

第二好的情况,你左右有一个人不为Null,说明找到了一个,那么你就把这个一个人交上去就行了

最差情况,左右为Null,一无所有,那么就把null交上去就行了。

在这里插入图片描述

两个指针同时往左或者往右走,
当遇到一个节点weiNull时候
直接返回另外一个节点就行了,因为另外一个节点下面挂着的节点会跟着一起走的。


版权声明:本文为qq_40707269原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。