104.二叉树的最大深度
BFS(迭代)法:
昨天二叉树的层序遍历十道题里出现了,简单写一下,层序遍历做还是比较简单的。
public int maxDepth(TreeNode root) {
// 1. BFS(迭代)法
if(root == null) {
return 0;
}
int depth = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
depth++; // 最外层while循环,控制的就是第几层的孩子节点入队,所以记录深度即可
int len = queue.size();
while(len > 0) {
TreeNode temp = queue.poll();
if(temp.left != null) {
queue.add(temp.left);
}
if(temp.right != null) {
queue.add(temp.right);
}
len--;
}
}
return depth;
}
n叉树也一样,改一部分就行:
public int maxDepth(Node root) {
// 1. BFS(迭代)法
if(root == null) {
return 0;
}
int depth = 0;
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
depth++; // 最外层while循环,控制的就是第几层的孩子节点入队,所以记录深度即可
int len = queue.size();
while(len > 0) {
Node temp = queue.poll();
// 由于是n叉树,所以两个if是不够的,用for循环让n个孩子节点入队
for(Node tree : temp.children) {
queue.add(tree);
}
len--;
}
}
return depth;
}
n叉树的区别就是,在让每一层节点的子结点入队时,要用for循环遍历孩子节点集合,示例输入中的:root = [1,null,3,2,4,null,5,6],其中1后面的null只是为了区分,实际写代码时并不用管,只需要看图就行,例如,根节点下,有三个孩子节点,所以temp.children=[3, 2, 4]。不用担心没有孩子的节点会导致队列存入null,没有孩子节点的节点就压根进入不了增强for循环遍历它的孩子节点。
DFS(递归)法:
首先搞明白深度和高度的概念,这里引用代码随想录里的总结:
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
以及代码随想录里的图:
总结:高度是从下往上。深度是从上往下。
再来做这道题,结合之前的“前/中/后”序遍历,可以总结出:前序求深度,后序求高度。
如何理解呢?其实就是看上面的例图,想要知道深度,就是每次遍历第一个节点,就让深度计数器加1,而高度则是要看当前这个节点,到叶子,所以需要有一个返回的过程,后序就很合适,而这道题却是用后序遍历,原因在于,求的是最大深度,最大深度就等同于“根节点高度”,所以,转化为后序遍历,问题就变得很简单了,当然硬要用前序遍历也能做,详细可以去代码随想录里查看源码。我下面是自己写的后序遍历求解:
后序遍历代码:
public int maxDepth(TreeNode root) {
// 2. DFS(递归)法:后序遍历
return getHeight(root);
}
public int getHeight(TreeNode root){
if(root == null){
return 0;
}
int leftHeight = getHeight(root.left); // 左
int rightHeight = getHeight(root.right);// 右
int height = 1+ Math.max(leftHeight, rightHeight);// 中:最终到了中间这个节点,中间这个点的高度就是左右子树的最大高度然后加上自己的高度1
return height;
}
111.二叉树的最小深度
BFS(迭代)法:
同样的,还是用BFS法先做一遍,只需要当遇到有某个节点的左右孩子都为空时,返回深度就行,如果一直没有,那也返回深度,此深度即是最小也是最大(最坏情况)。
public int minDepth(TreeNode root) {
// 1. BFS(迭代)法
if(root == null) {
return 0;
}
int depth = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
depth++; // 最外层while循环,控制的就是第几层的孩子节点入队,所以记录深度即可
int len = queue.size();
while(len > 0) {
TreeNode temp = queue.poll();
if(temp.left != null) {
queue.add(temp.left);
}
if(temp.right != null) {
queue.add(temp.right);
}
if(temp.left == null && temp.right == null) {
return depth; // 当没有左右孩子时即是第一个叶子(因为是从左往右,遇到了一个就可以返回最小深度了),返回这一层的层数(深度)
}
len--;
}
}
return depth;
}
222.完全二叉树的节点个数
BFS(迭代)法:
显然的显然,这题还是可以用层序遍历法去做,理解透了层序遍历法,就是轻松,但是一层一层的遍历速度肯定是慢的,但是好理解才是王道。
public int countNodes(TreeNode root) {
// 1. BFS(迭代)法
if(root == null) {
return 0;
}
int count = 1; // 已经有一个根节点了,从1开始记数
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
int len = queue.size();
while(len > 0) {
TreeNode temp = queue.poll();
if(temp.left != null) {
queue.add(temp.left);
count++; // 每加入一个节点,则计数器加1
}
if(temp.right != null) {
queue.add(temp.right);
count++;
}
len--;
}
}
return count;
}
DFS(递归)法:
前序遍历,访问节点就是计数器加1即可。
class Solution {
int count = 0;
public int countNodes(TreeNode root) {
// DFS(递归)法
if(root == null) {
return 0;
}
count++; // 访问节点的操作就是计数器加1
countNodes(root.left);
countNodes(root.right);
return count;
}
}