Leetcode题目-104. Maximum Depth of Binary Tree
链接: 104. Maximum Depth of Binary Tree
思路
这道题在层序遍历里面已经做过一次了,利用层序遍历的思路也容易理解,得到结果。这里主要讨论一下它的递归做法,同时巩固一下对递归思路的掌握。
- 递归函数:根据根节点求深度,
public int maxDepth(TreeNode root)
- 递归终止条件:
if (root == null) { return 0;}
- 单次递归逻辑:求左子树深度,求右子树深度,再加上自身深度
代码实现
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int depth = 0;
depth = 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
return depth;
}
}
Leetcode题目-559. Maximum Depth of N-ary Tree
链接: 559. Maximum Depth of N-ary Tree
思路
n叉树的原理几乎同理,可以使用层序遍历的迭代法求解,只不过在处理左右子树的步骤,是遍历n叉树的所有子树。同时这里也主要讨论其递归法。
- 递归函数:根据根节点求深度,
public int maxDepth(Node root)
- 递归终止条件:
if (root == null) { return 0;}
- 单次递归逻辑:获取每一个子树的深度,去最大值,并加上自身深度
代码实现
class Solution {
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 1 + depth;
}
}
Leetcode题目-111. Minimum Depth of Binary Tree
链接: 111. Minimum Depth of Binary Tree
思路
最小值需要注意,这里可不是把上题的求最大值换成求最小值就可以了,这里会遇到一种特殊情况,就是当节点左子树为空,右子树不为空时,此时它并不是一个叶子节点,但是取子树的最小深度会取成0,从而把它误认为是一个叶子节点。所以需要分别判断左右子树是否为空的情况。
如果使用层序遍历迭代法也可以较容易求的。
代码实现
class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right != null) {
return minDepth(root.right) + 1;
}
if (root.left != null && root.right == null) {
return minDepth(root.left) + 1;
}
return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
}
}
Leetcode题目-222. Count Complete Tree Nodes
链接: 222. Count Complete Tree Nodes
思路
这里使用递归和迭代可以将此完全二叉树当作普通二叉树处理,但是这样的复杂度是O(n),且没有用到完全二叉树的特性,题目中也提出要求复杂度小于O(n)。所以我们要用到完全二叉树的特性来求解。作为一个完全二叉树,其只有可能是满二叉树或最底层叶子结点未满两种情况。对于满二叉树,其有特点,一个深度为n的满二叉树,其节点个数为2^n-1个,所以可以利用这一特性求节点数;对于最底层叶子结点未满的情况,可以分别递归其左右子树,在某一深度,总会出现满二叉树(叶子结点也算是一个深度为1的满二叉树)。这样求解的时间复杂度,为O(logn * logn)。
代码实现
1. 普通二叉树递归
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
2. 利用完全二叉树特性(写法一)
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
TreeNode cur = root;
// 这里深度是包括根节点的,从1开始算
int leftDepth = 0;
int rightDepth = 0;
while (cur != null) {
leftDepth++;
cur = cur.left;
}
cur = root;
while (cur != null) {
rightDepth++;
cur = cur.right;
}
if (leftDepth == rightDepth) {
return (1 << leftDepth) - 1;
}
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
2. 利用完全二叉树特性(写法二)
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = getDepth(root.left);
int rightDepth = getDepth(root.right);
// 左右子树深度相同,则此时左子树一定被填满了,为满二叉树
if (leftDepth == rightDepth) {
// 左子树节点数为1<<leftDepth-1
// 根节点节点数+1
// 右子树继续计算(因为叶子结点也算一个满二叉树,所以最后总会遍历结束,不会存在死循环)
return (1 << leftDepth) + countNodes(root.right);
// 左右子树深度不相同,则左子树不一定为满二叉树(树的最后一层没满),但倒数第二层一定满了,所以右子树的一定为满二叉树
} else {
return (1 << rightDepth) + countNodes(root.left);
}
}
private int getDepth(TreeNode root) {
int depth = 0;
while (root != null) {
depth++;
root = root.left;
}
return depth;
}
}