思路1:递归
写法构思:传入某节点,调用该方法,返回的应该是以传入节点为根节点的树的深度,而树的深度,肯定和左右子树深度有关,所以进入这个方法后,就包含了左右子树的深度(而要得到左右子树的深度,肯定又是以左右子节点为根节点,再次调用该方法深度获取的,因此此时进行递归),并且还有由一个左右深度比较的过程,然后取较大值,这个较大值就是该节点左右子树深度较深的值,以该值+1作为返回值,就是该节点的深度。
因此,方法名TreeDepth,在方法中,申明两个变量分别记录得到的左右子树深度。
int left = node.TreeDpth(Root.left);// 显然需要把当前节点的左节点传入,进行递归调用 int right = node.TreeDpth(Root.right);
然后进行比较,较大值+1作为返回值。
return left > right ? left + 1 : right + 1;
再考虑递归结束条件,当传入节点的左右子节点,有为空的时候,应该返回0;这样就表示,传入的节点,左右子树为空时,左右子树的深度为0。显然这部分代码应该在调用递归之前执行,到了空直接return,不满足空就说明还有子树,继续递归
if(Root == null){ return 0; }
因此将代码组合起来,就是答案
import java.util.Queue; import java.util.LinkedList; public class Solution { public int TreeDepth(TreeNode Root) { if(Root == null){ return 0; } int left = TreeDepth(Root.left); int right = TreeDepth(Root.right); return left > right ? left + 1 : right + 1; } }
2.非递归写法
写法构思:利用的队列,首先给入的是根节点,使其入队,遍历某个节点时,将该节点出队,并将该节点的所有子节点入队,当同一深度的节点都遍历完的时候,深度++,所以设depth是深度。count是已经当前层(同一深度层)出队列的节点数(已遍历),nextcount是当前层的节点总数。所以当count等于nextcount就意味着当前层已遍历完,需要将当前节点数count置为0,在再弹出节点时。进行深度++操作。并重新更新nextcount的值
因此需要不断的从队列中取、放节点。通过while进行循环,而队列为空时,说明所有节点都遍历了,返回最终的depth。而只要队列不为空,就需要进行遍历和后续的操作。
因此,首先创建队列,将根节点入队
queue.add(root);
判断队列是否为空(此时进入while循环过程),将根(当前节点)节点出队,count++;
TreeNode top = queue.poll(); count++;
然后将根节点(当前节点)的子节点入队
if(top.left != null){ queue.add(top.left); } if(top.right != null){ queue.add(top.right); }
判断count和nextcount大小,不相等说明同一深度层没有遍历完,继续while过程,进行出队,count++,直到count递增到和nextcount相同时,说明同一深度层遍历完,此时深度depth++,并且需要将count重新置为0
if(count == nextCount){ nextCount = queue.size(); count = 0; depth++; }
注意此时的队列中,由于同一深度层A全部遍历完并且出队,而且在A层遍历的时候,已经将A层子节点全部入队了,此时队列中存放的是深度为A+1层的所有节点,所以此时应给nextcount赋值为队列的size,更新的nextcount就是深度A+1层的所有节点数,而下次从队列中取节点时,也是A+1层的节点了(完成了一个深度为A的遍历).nextcount的初始值应该为1(就根节点一个),第一次是根节点入队出队,队列长度为1.
//因此赋初始值时 这是在while过程外赋值 int depth = 0, count = 0, nextCount = 1;
因此,考虑根节点为空的情况,再将思路各个部分组合起来就是答案
import java.util.Queue; import java.util.LinkedList; public class Solution { public int TreeDepth(TreeNode root) { if(root == null){ return 0; } Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.add(root); int depth = 0, count = 0, nextCount = 1; while(queue.size()!=0){ TreeNode top = queue.poll(); count++; if(top.left != null){ queue.add(top.left); } if(top.right != null){ queue.add(top.right); } if(count == nextCount){ nextCount = queue.size(); count = 0; depth++; } } return depth; } } //这里其实还可以写成,每添加一个,就让深度++,最后深度的变量赋值给nextcount
5.20更新
对于非递归层次遍历写法,可以有如下写法。
public int maxDepth(TreeNode root) { if (root == null) { return 0; } //BFS的层次遍历思想,记录二叉树的层数, //遍历完,层数即为最大深度 LinkedList<TreeNode> queue = new LinkedList<>(); queue.add(root); int maxDepth = 0; while (!queue.isEmpty()) { maxDepth++; int size = queue.size();//先获取本层的节点数,然后遍历,之前的是边遍历,边判断 for (int i = 0; i < size; i++) { TreeNode node = queue.poll(); if (node.left != null) { queue.add(node.left); } if (node.right != null) { queue.add(node.right); } } } return maxDepth; }
使用栈也是可以解题。只不过入栈时还要带上该节点的深度的信息。也就是说,入栈的不是节点,而是一个包含节点和该节点深度的一个对象。所以要建一个类。
力扣题解
/** * DFS迭代实现二叉树最大深度 * 时间复杂度O(n) * 空间复杂度:线性表最差O(n)、二叉树完全平衡最好O(logn) * * @param root 根节点 * @return 最大深度 */ private static int maxDepth2(TreeNode root) { if (root == null) { return 0; } LinkedList<Pair<TreeNode, Integer>> stack = new LinkedList<>(); stack.push(new Pair<>(root, 1)); int maxDepth = 0; //DFS实现前序遍历,每个节点记录其所在深度 while (!stack.isEmpty()) { Pair<TreeNode, Integer> pair = stack.pop(); TreeNode node = pair.first; //DFS过程不断比较更新最大深度 maxDepth = Math.max(maxDepth, pair.second); //记录当前节点所在深度 int curDepth = pair.second; //当前节点的子节点入栈,同时深度+1 if (node.right != null) { stack.push(new Pair<>(node.right, curDepth + 1)); } if (node.left != null) { stack.push(new Pair<>(node.left, curDepth + 1)); } } return maxDepth; }