104.二叉树的最大深度
思路:求解根节点的高度就是二叉树的最大深度。采用后序遍历的方法来求解根节点的高度。也可以用前序遍历来直接求解二叉树的深度。(层序遍历也可以求解二叉树深度。(迭代法))
后序求解根节点高度
/***** 解法一,回溯算法思路 *****/
class Solution {
int depth = 0;
int res = 0;
public int maxDepth(TreeNode root) {
traverse(root);
return res;
}
// 遍历二叉树
void traverse(TreeNode root) {
if (root == null) {
return;
}
// 前序遍历位置
depth++;
// 遍历的过程中记录最大深度
res = Math.max(res, depth);
traverse(root.left);
traverse(root.right);
// 后序遍历位置
depth--;
}
}
/***** 解法二,动态规划思路 *****/
class Solution2 {
// 定义:输入一个节点,返回以该节点为根的二叉树的最大深度
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftMax = maxDepth(root.left);
int rightMax = maxDepth(root.right);
// 根据左右子树的最大深度推出原二叉树的最大深度
return 1 + Math.max(leftMax, rightMax);
}
}
层序遍历(迭代法)求解深度。
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
int deep = 0;
// while 循环控制从上向下一层层遍历
while (!q.isEmpty()) {
// 存储当前层的节点个数
int sz = q.size();
// for 循环控制每一层从左向右遍历
for (int i = 0; i < sz; i++) {
TreeNode cur = q.poll();
if (cur.left != null)
q.offer(cur.left);
if (cur.right != null)
q.offer(cur.right);
}
deep++;
}
return deep;
}
}
559.N叉树的最大深度
思路:二叉树的递归分为「遍历」和「分解问题」两种思维模式,这道题两种思维模式都可以使用。同样可以用迭代法(层序遍历)求解。
// 分解问题的思路
class Solution {
public int maxDepth(Node root) {
if (root == null) {
return 0;
}
int subTreeMaxDepth = 0;
for (Node child : root.children) {
subTreeMaxDepth = Math.max(subTreeMaxDepth, maxDepth(child));
}
return 1 + subTreeMaxDepth;
}
}
// 遍历的思路
class Solution2 {
public int maxDepth(Node root) {
traverse(root);
return res;
}
// 记录递归遍历到的深度
int depth = 0;
// 记录最大的深度
int res = 0;
void traverse(Node root) {
if (root == null) {
return;
}
// 前序遍历位置
depth++;
res = Math.max(res, depth);
for (Node child : root.children) {
traverse(child);
}
// 后序遍历位置
depth--;
}
}
层序遍历(迭代法)求解深度。
class Solution {
// 迭代法,使用层序遍历
public int maxDepth(Node root) {
if (root == null) return 0;
int depth = 0;
Queue<Node> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
depth ++;
int len = q.size();
while (len > 0) {
Node node = q.poll();
for (int i = 0; i < node.children.size(); i++)
if (node.children.get(i) != null)
q.offer(node.children.get(i));
len--;
}
}
return depth;
}
}
111.二叉树的最小深度
最小深度是指从根节点到最近叶子节点的最短路径上的节点数量。
思路:采用后序递归遍历求根节点的最小高度(就是二叉树的最小深度)。也可以使用层序遍历(迭代法)。求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。
class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftMinDepth = minDepth(root.left);
int rightMinDepth = minDepth(root.right);
// 当一个左子树为空,右不为空,这时并不是最低点
if (root.left == null && root.right != null) {
return rightMinDepth + 1;
}
// 当一个右子树为空,左不为空,这时并不是最低点
if (root.left != null && root.right == null) {
return leftMinDepth + 1;
}
return 1 + Math.min(leftMinDepth, rightMinDepth);
}
}
层序遍历(迭代法)求解深度。
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
// root 本身就是一层,depth 初始化为 1
int depth = 1;
while (!q.isEmpty()) {
int sz = q.size();
/* 遍历当前层的节点 */
for (int i = 0; i < sz; i++) {
TreeNode cur = q.poll();
/* 判断是否到达叶子结点 */
if (cur.left == null && cur.right == null)
return depth;
/* 将下一层节点加入队列 */
if (cur.left != null)
q.offer(cur.left);
if (cur.right != null)
q.offer(cur.right);
}
/* 这里增加深度 */
depth++;
}
return depth;
}
}
222.完全二叉树的节点个数
层序遍历实现(适用所有二叉树)
class Solution {
public int countNodes(TreeNode root) {
if(root == null) return 0;
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
int count = 0;
while(!q.isEmpty()) {
TreeNode node = q.poll();
count++;
if(node.left != null) {
q.add(node.left);
}
if(node.right != null) {
q.add(node.right);
}
}
return count;
}
}
后序递归遍历实现(适用所有二叉树)
class Solution {
// 后序递归遍历实现
public int countNodes(TreeNode root) {
if (root == null) return 0;
int countLeft = countNodes(root.left);
int countRight = countNodes(root.right);
return 1 + countLeft + countRight;
}
}
后序递归遍历(用于完全二叉树)
一棵完全二叉树的两棵子树,至少有一棵是满二叉树。计算满二叉树的节点个数不用一个个节点去数,可以直接通过树高算出来,这也是这道题提高效率的关键点。
class Solution {
public int countNodes(TreeNode root) {
TreeNode l = root, r = root;
// 记录左、右子树的高度
int hl = 0, hr = 0;
while (l != null) {
l = l.left;
hl++;
}
while (r != null) {
r = r.right;
hr++;
}
// 如果左右子树的高度相同,则是一棵满二叉树
if (hl == hr) {
return (int) Math.pow(2, hl) - 1;
}
// 如果左右高度不同,则按照普通二叉树的逻辑计算
return 1 + countNodes(root.left) + countNodes(root.right);
}
}