oHo 原来是二叉树

38 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

这几天在牛客刷题,又发现了一些小规律哈哈,虽然之前写过了,但是当作复习吧。 二叉树的递归算法模板 - 掘金 (juejin.cn)

主要来源这几个题:

image.png

手先(首先)最基本的二叉树的递归遍历,你得会吧。

复习一下:

先中后序遍历

  • 先序遍历:根-》左-》右
  • 中序遍历:左-》根-》右
  • 先序遍历:左-》右-》根

代码

public int[] preorderTraversal (TreeNode root) {
        List<Integer> list=new ArrayList<>();
        pre(list,root);
        int []res=new int[list.size()];
        for(int i=0;i<list.size();i++){
            res[i]=list.get(i);
        }
        return res;
       
    }
    public void pre(List<Integer> list,TreeNode root){
        if(root==null) return;
        list.add(root.val);
        pre(list,root.left);
        pre(list,root.right);
    }

list.add(root.val); pre(list,root.left); pre(list,root.right); 这几行代码就是做先序中序后序的关键,可以通过修改list.add和其他两行顺序达到目的。这个就不用再说了吧。

补充:当题目给的方法里面返回值是int[]数组,大概率需要声明ArrayList,通过它来得到。

至于后面声明数组和遍历赋值,是arrlist变成数组常用的,可以当作模板吧,后面问题也会遇到。

接下来就是层次遍历:

image.png

首先根据返回值类型,声明一个list对象,然后进行边界值的判断(二叉树里面就算传入树为空情况),判断边界值的返回值。

接下来考虑,怎么层次遍历。我们可以把结点放到一个队列里面,然后进行弹出,弹出后再次判断它的左右结点在不在,继续添加到队列(因为队列吓人线程,使用如果根节点的左孩子弹出时候,第三层的孩子在根节点的右孩子后面,使用不会影响弹出。)每次完成都需要把内层的list放入结果对象里面。

同理,关于怎么求二叉树最大深度,也可以通过层次遍历

image.png

n1++在for循环外,表示层数,即深度。如果n1++在for循环内部,那么就算统计有几个节点。

类似的:比如之字形遍历二叉树。 只需要加一个flag,当它等于true,就进行从右到左遍历。

image.png

这种解法并没有体现要怎么从右边开始遍历,而是通过内层循环arr是Arraylist,然后调用集合的reverse方法对当前层数据进行反转,然后加入反转数到res里面。

并且在遍历每一层的时候,flag的值都取反,避免了需要写明第几层是true,第几层是false。

重建二叉树。

当我们已知先序和中序遍历可以,推出后序遍历,也可以构造出这棵二叉树。

image.png

image.png

那么代码部分,首先判断极端情况,即树为空,即先序中序遍历数组长度为0。

然后声明一个树,传入参数先序第一个数的值。这样就能拿到根节点了。后面就开始循环遍历中序数组,当中序数组当前值等于先序的根,就分成两部分。前面配合先序的,可以再次调用当前函数

image.png

输出二叉树的右视图

image.png

首先,外卖可以通过两个数组新建一个树。然后对树进行层次遍历,当遍历到每一层最后一个数,就把他加入结果list

image.png

二叉树的和为某个值的路径

首先判断当树为空时候,没有解。

当树的左孩子为空,右孩子为空,并且根的值等于sum,返回true。

否则进行递归调用,传入左孩子或者右孩子

image.png

树的公共祖先

其实就是找根节点到两个目标节点的路径,返回路径里面最后一个相同点。

相似的二叉搜索树(左<根<右)公共节点。

同样是先求到路径。

怎么求路径?

声明list集合,对数组进遍历

image.png

对称二叉树

其实就是:root.left.left==root.right.right root.left.lright==root.right.left

image.png

类似,二叉树的镜像对称。

image.png

总结:

  1. 二叉树返回值声明样,就先声明什么样的对象,如果返回数组右边声明集合。
  2. 先考虑极端情况
  3. 对于递归模板里面的几个反复使用
  4. 重点层次遍历,对称
  5. 我没有系统学过声明背包等内容,只是通过这几个题,找的规律,可能是片面的,作为参考吧。