二叉树的深度
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
例如:
给定二叉树 `[3,9,20,null,null,15,7]`,
3
/ \
9 20
/ \
15 7
返回它的最大深度 3
递归:
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
层次遍历:
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
Queue queue=new LinkedList<>();
queue.offer(root);
int dept=0;
while(!queue.isEmpty()){
//当前队列的大小即为这一层结点的个数
int count=queue.size();
//将这一层所有结点的孩子加入队列
for (int i = 0; i
二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:2
层次
当遇到左右子树都为空的时候返回
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
Queue queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()) {
int count = queue.size();
depth++;
for (int i = 0; i < count; i++) {
TreeNode node = queue.poll();
if (node.left == null && node.right == null) {
return depth;
}
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
return 0;
}
递归
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
int min = Integer.MAX_VALUE;
if (root.left != null) {
min = Math.min(min, minDepth(root.left));
}
if (root.right != null) {
min = Math.min(min, minDepth(root.right));
}
return min + 1;
}
N 叉树的最大深度
给定一个 N 叉树,找到其最大深度。
最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。
示例 1:
输入:root = [1,null,3,2,4,null,5,6]
输出:3
迭代
public int maxDepth(Node root) {
if (root == null) {
return 0;
}
Queue queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()) {
int count = queue.size();
for (int i = 0; i < count; i++) {
root = queue.poll();
for (Node node : root.children) {
queue.add(node);
}
}
depth++;
}
return depth;
}
递归
public int maxDepth(Node root) {
if (root == null) {
return 0;
}
int depth = 0;
for (Node node : root.children) {
depth = Math.max(depth, maxDepth(node));
}
return depth + 1;
}
平衡二叉树
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 `false`
限制:
1 <= 树的结点个数 <= 10000
方法一:自顶向下
- 判断当前子树是否平衡
- 判断左子树是否平衡
- 判断右子树是否平衡
明显会存在重复计算
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
return Math.abs(maxDepth(root.left) - maxDepth(root.right)) <= 1
&& isBalanced(root.left) && isBalanced(root.right);
}
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
时间复杂度:O(nlogn)
isBalanced会遍历所有结点O(n),计算结点的深度O(logn)
空间复杂度:O(n)
如果树完全倾斜,递归栈可能包含所有节点
方法二:自底向上
先判断子树是否平衡(如果不平衡直接返回),再判断当前是否平衡
public boolean isBalanced(TreeNode root) {
return depth(root) != -1;
}
public int depth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = depth(root.left);
if (leftDepth == -1) {//不平衡,剪枝
return -1;
}
int rightDepth = depth(root.right);
if (rightDepth == -1) {
return -1;
}
return Math.abs(leftDepth - rightDepth) <= 1 ?
Math.max(leftDepth, rightDepth) + 1 : -1;
}
时间复杂度O(n)
空间复杂度O(n)
二叉树的直径
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
示例 :
给定二叉树
1
/ \
2 3
/ \
4 5
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]
相当于计算两个结点间的路径长度,最长的路径必定来自于叶子结点
两个叶子结点的路径等于两个结点的深度之和
相当于找到哪两个叶子结点的深度之后最大
private int maxDiameter;
public int diameterOfBinaryTree(TreeNode root) {
depth(root);
return maxDiameter;
}
public int depth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = depth(root.left);
int rightDepth = depth(root.right);
maxDiameter = Math.max(maxDiameter, leftDepth + rightDepth);
return Math.max(leftDepth, rightDepth) + 1;
}