递归
从实现上想,深度优先说明他会遍历到最后子节点,哪怕该层没有遍历完,所以递归时,要带着一个层数的var,这样,每一层会根据这个参数找到相应的list 加进去
- 截至条件: 找到了空Node, 结束
- 输入: 深度,当前的node。 输出void 把res List 作为全局变量
- 单层逻辑:
进入新的一个ufnction 意味着新加一个deep --> deep+1
每一次递归都要检查有没有进入到新的一层 如果 List.size() < deep(肯定会有大于的可能) 就要新加一层
把 该层的node 加到该层的list里,记得是从0开始,所以get(deep - 1)
迭代
Queue 的存在是因为二叉树本身的结构是没有办法同时保存层数和该层信息的,所以这道题用queue 保存多层的信息,之后根据另外一个变量 size(这个很重要) 去控制Pop 出来多少个node也就是该层的所有点
对于自己来说: 一个很大的问题就是这个size 一直不知道如何去赋值。
还是看了题解,首先2层循环, 第一个是为了遍历整棵树的循环(queue为空说明没有Node了)内层循环是为了遍历整层,而如何知道是哪一层呢? 就需要一个var 存储着信息,循环时递减。那他到底在什么时候开始记录信息呢?因为Queue里存储的其实是2层的信息,所以每次Push之后size++ 肯定是不现实的。
所以在 还没有来得及加新node,上一层旧node被pop掉的时候,就是要记录size的时候,也就是跳出第二层循环的时候,赶紧在数一下queue 的 size,并且记录下来,这样之后哪怕又新加了新节点size变化了,也不会影响循环次数
接下来的几道题都是基于层序遍历的操作上加一些别的操作判定:
题目和链接如下:
107.二叉树的层次遍历 II
直接把106的结果反转(reverse) 一下, 就好啦
199.二叉树的右视图
只要最右边的node,那就在放入结果List 的时候 只要sizde ==1 说明遍历到了最后一个点,加入该判定条件即可。
637.二叉树的层平均值
这个计算的逻辑很简单,遍历完每层之后计算,记住要把Num 一开始记录下来,等sum算好之后再除。
一个很小的点需要注意的就是,sum 有没有可能overflow(- 2 32/2 - 2 32/2 )(-2147483647). 所以sum 是需要用 Long 存储的。
同理,如果有除法,要记得会不会有除数为0的情况
429.N叉树的层序遍历
觉得题目简单,太过于轻敌,要注意审题。children是一个List 不是一个点了,所以直接遍历children(之前需要判定是否为空)即可
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度
以上是用层序遍历可以编写的题目。下面是今日任务剩下的2道题
226.翻转二叉树
用前序
不能用中序
确认递归的3个条件:
输入返回值:输入 node, 返回void 因为直接对树进行操作
截止条件: 找到空
单层递归的逻辑:把该节点的左右节点swap.
在这里要注意一个点,就是JAVA中都是传值调用。在swap函数中,我们如果传入root. 其实传入的是指向 root 的地址,这样右任何的操作都是对这个地址的操作,swap了地址就swap了指针。
但是如果只是传进去2个root.left && root.right.
101. 对称二叉树
判定并不是简单的 左右子树的比较,而是左外侧的节点数值和右外侧节点数值的比较
以何种遍历方式:? 答: 后序。 因为父节点需要接受到子节点的信息(即是否对称)然后将这个信息向上传递,最后才能获得答案。
递归确定:
- 返回值: 输出是boolean 输入是左右节点
- 截止条件:遍历到了最后 都为空 = 说明true || 只有一个为空 肯定不对称 false
- 单层递归:没有操作
迭代: 比较巧妙的用一个deque 或者一个queue, 把遍历到的点对称的offer 进去再pop 出来,以上的截止条件在这里也可以运用。不过有一点不用就是,如果Poll 出来都是空的话,迭代里说明可能只是只有一边的节点为空,直接continue继续pop下一个比较 (但是递归中,出现这样的情况就说明已经遍历到了最后,即一直都是对称的状态,返回 true)
我自己写的错误是如果值是相等的, 我就会直接返回true, 但是其实只是说明暂且满足,还没有比完所有的节点,所以并不能直接返回true