开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情
这几天在牛客刷题,又发现了一些小规律哈哈,虽然之前写过了,但是当作复习吧。 二叉树的递归算法模板 - 掘金 (juejin.cn)
主要来源这几个题:
手先(首先)最基本的二叉树的递归遍历,你得会吧。
复习一下:
先中后序遍历
- 先序遍历:根-》左-》右
- 中序遍历:左-》根-》右
- 先序遍历:左-》右-》根
代码
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变成数组常用的,可以当作模板吧,后面问题也会遇到。
接下来就是层次遍历:
首先根据返回值类型,声明一个list对象,然后进行边界值的判断(二叉树里面就算传入树为空情况),判断边界值的返回值。
接下来考虑,怎么层次遍历。我们可以把结点放到一个队列里面,然后进行弹出,弹出后再次判断它的左右结点在不在,继续添加到队列(因为队列吓人线程,使用如果根节点的左孩子弹出时候,第三层的孩子在根节点的右孩子后面,使用不会影响弹出。)每次完成都需要把内层的list放入结果对象里面。
同理,关于怎么求二叉树最大深度,也可以通过层次遍历
n1++在for循环外,表示层数,即深度。如果n1++在for循环内部,那么就算统计有几个节点。
类似的:比如之字形遍历二叉树。 只需要加一个flag,当它等于true,就进行从右到左遍历。
这种解法并没有体现要怎么从右边开始遍历,而是通过内层循环arr是Arraylist,然后调用集合的reverse方法对当前层数据进行反转,然后加入反转数到res里面。
并且在遍历每一层的时候,flag的值都取反,避免了需要写明第几层是true,第几层是false。
重建二叉树。
当我们已知先序和中序遍历可以,推出后序遍历,也可以构造出这棵二叉树。
那么代码部分,首先判断极端情况,即树为空,即先序中序遍历数组长度为0。
然后声明一个树,传入参数先序第一个数的值。这样就能拿到根节点了。后面就开始循环遍历中序数组,当中序数组当前值等于先序的根,就分成两部分。前面配合先序的,可以再次调用当前函数
输出二叉树的右视图
首先,外卖可以通过两个数组新建一个树。然后对树进行层次遍历,当遍历到每一层最后一个数,就把他加入结果list
二叉树的和为某个值的路径
首先判断当树为空时候,没有解。
当树的左孩子为空,右孩子为空,并且根的值等于sum,返回true。
否则进行递归调用,传入左孩子或者右孩子
树的公共祖先
其实就是找根节点到两个目标节点的路径,返回路径里面最后一个相同点。
相似的二叉搜索树(左<根<右)公共节点。
同样是先求到路径。
怎么求路径?
声明list集合,对数组进遍历
对称二叉树
其实就是:root.left.left==root.right.right root.left.lright==root.right.left
类似,二叉树的镜像对称。
总结:
- 二叉树返回值声明样,就先声明什么样的对象,如果返回数组右边声明集合。
- 先考虑极端情况
- 对于递归模板里面的几个反复使用
- 重点层次遍历,对称
- 我没有系统学过声明背包等内容,只是通过这几个题,找的规律,可能是片面的,作为参考吧。