今日任务
力扣 104. 二叉树的最大深度, 559. N 叉树的最大深度, 111. 二叉树的最小深度, 222. 完全二叉树的节点个数
递归法
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层递归的逻辑
迭代法:
使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
题目 :104. 二叉树的最大深度
思路
题解
1.递归
本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
而根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。
class solution {
/**
* 递归法
*/
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}
}
// 简化版写法
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
2.迭代法,层序遍历
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int depth = 0;
while (!deque.isEmpty()) {
int size = deque.size();
depth++;
for (int i = 0; i < size; i++ ) {
TreeNode tmp = deque.poll();
if (tmp.left != null) {
deque.offer(tmp.left);
}
if (tmp.right != null) {
deque.offer(tmp.right);
}
}
}
return depth;
}
}
题目 :559. N 叉树的最大深度
思路
同上题,子树遍历细节略有不同
题解
1.递归
class Solution {
public int maxDepth(Node root) {
if (root == null) return 0;
int depth = 0;
if (root.children != null) {
for (Node child : root.children) {
depth = Math.max(depth, maxDepth(child));
}
}
return depth + 1;
}
}
2.迭代法,层序遍历 + 队列
class Solution {
public int maxDepth(Node root) {
if (root == null) return 0;
Deque<Node> deque = new LinkedList<>();
deque.offer(root);
int depth = 0;
while (!deque.isEmpty()) {
depth++;
int len = deque.size();
while (len-- > 0) {
Node tmp = deque.poll();
for (int i = 0; i < tmp.children.size(); i++ ) {
if (tmp.children.get(i) != null) {
deque.offer(tmp.children.get(i));
}
}
}
}
return depth;
}
}
题目 :111. 二叉树的最小深度
思路
有一个坑:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
什么是叶子节点,左右孩子都为空的节点才是叶子节点!
如果这么求的话,没有左孩子的分支会算为最短深度,但!这是不对的
所以,如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。
题解
1.递归法
相比求MaxDepth要复杂点,因为最小深度是从根节点到最近叶子节点的最短路径上的节点数量
class Solution {
public String reverseWords(String s) {
// 1.去除 前 中 后 空格
StringBuilder sb = reverseSpace(s);
// 2.整体反转
reverseString(sb, 0, sb.length() - 1);
// 3.单词反转
reverseEachWorld(sb);
return sb.toString();
}
private StringBuilder reverseSpace(String s){
int start = 0;
int end = s.length() - 1;
while (s.charAt(start) == ' ') start++;
while (s.charAt(end) == ' ') end--;
StringBuilder sb = new StringBuilder();
while (start <= end) {
char c = s.charAt(start);
if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
start++;
}
return sb;
}
private void reverseString(StringBuilder sb, int start, int end) {
while (start < end) {
char tmp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, tmp);
start++;end--;
}
}
private void reverseEachWorld(StringBuilder sb) {
int start = 0;
int end = 1;
int n = sb.length();
while (start < n) {
while (end < n && sb.charAt(end) != ' ') {
end++;
}
reverseString(sb, start, end - 1);
start = end + 1;
end = start + 1;
}
}
}
2.递归法(思路来自二叉树最大深度的递归法)
该题求最小深度,最小深度为根节点到叶子节点的深度,所以在迭代到每个叶子节点时更新最小值。
class Solution {
int depth = 0;
int minDepth = Integer.MAX_VALUE;
public int minDepth(TreeNode root) {
dep(root);
return minDepth == Integer.MAX_VALUE ? 0 : minDepth;
}
public void dep(TreeNode node) {
if (node == null) return ;
depth++;
dep(node.left);
dep(node.right);
if (node.left == null && node.right == null) {
minDepth = Math.min(minDepth, depth);
}
depth--;
}
}
3.迭代法,层序遍历
需要注意的是,只有当左右孩子都为空的时候,才说明遍历到最低点了。如果其中一个孩子不为空则不是最低点
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int depth = 0;
while (!deque.isEmpty()) {
int size = deque.size();
depth++;
for (int i = 0; i < size; i++ ) {
TreeNode tmp = deque.poll();
if (tmp.left == null && tmp.right == null) {
return depth;
}
if (tmp.left != null) deque.offer(tmp.left);
if (tmp.right != null) deque.offer(tmp.right);
}
}
return depth;
}
}
题目 :222. 完全二叉树的节点个数
思路
在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
题解
1.递归
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
2.递归
针对完全二叉树的解法
满二叉树的结点数为:2^depth - 1
首先,让我们理解代码中的两个while循环和接下来的if判断:
-
左子树深度计算 (
while (left != null)):这个循环通过持续访问左子树的左孩子节点来计算左子树的深度。因为在一个完全二叉树中,如果我们一直沿着左边走到底,可以达到的深度是树的最大深度。 -
右子树深度计算 (
while (right != null)):这个循环通过持续访问右子树的右孩子节点来计算右子树的深度。在一个完全二叉树中,如果右子树的深度与左子树的深度相同,那么这棵树是一棵满二叉树。 -
判断是否为满二叉树 (
if (leftDepth == rightDepth)):如果左右子树的深度相同,那么根据完全二叉树的性质,这颗树是一棵满二叉树。此时,我们可以直接使用公式 (2^depth)−1 来计算节点数,这里使用的是位移操作2 << leftDepth来计算 2^(leftDepth + 1),然后再减去1来得到节点总数。
如果左右子树深度不同,则说明最底层不是完全填满的,我们需要递归地计算左子树和右子树的节点数,再加上根节点本身,即 countNodes(root.left) + countNodes(root.right) + 1。
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
TreeNode left = root.left;
TreeNode right = root.right;
int leftDepth = 0, rightDepth = 0;
while (left != null) {
left = left.left;
leftDepth++;
}
while (right != null) {
right = right.right;
rightDepth++;
}
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1;
}
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
3.迭代法
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int result = 0;
while (!que.isEmpty()) {
int size = que.size();
while (size-- > 0) {
TreeNode tmp = que.poll();
result++;
if (tmp.left != null) que.offer(tmp.left);
if (tmp.right != null) que.offer(tmp.right);
}
}
return result;
}
}
本文详细探讨了如何使用递归和迭代方法解决二叉树、N叉树的最大深度问题,以及如何计算完全二叉树的节点个数,涉及到了层序遍历和递归终止条件的运用。
583

被折叠的 条评论
为什么被折叠?



