leetcode算法练习
104.二叉树的最大深度
题目链接
理解深度和高度
- 深度:任意一个结点到根结点的距离
- 高度:任意一个结点到叶子结点的距离
求深度——前序遍历:因为符合我们从上往下遍历的过程
求高度——后序遍历:因为是从下往上计数的 通过后序遍历的左右根 将叶子结点的高度返回给父结点 父结点知道其叶子结点的高度+1即可
但本题的关键所在就是!!!!根节点的高度就是就是该二叉树的最大深度——所以可以使用后序遍历来解决
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
// 遇到空 空结点高度为0
if (root == null) {
return 0;
}
// 后序遍历
// 左结点的高度
int leftDepth = maxDepth(root.left);
// 右结点的高度
int rightDepth = maxDepth(root.right);
// 左右取最大后+1
return Math.max(leftDepth, rightDepth) + 1;
}
}
111.二叉树的最小深度
题目链接
本题中要求最小深度是从根节点到最近叶子节点的最短路径上的节点数量
思路:
- 利用后序遍历来处理 因为根结点的最小高度就是二叉树的最小深度 求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
// 递归到为空 空结点高度为0
if (root == null) {
return 0;
}
// 后序遍历
// 求左子树的最小高度
int leftDepth = minDepth(root.left);
// 求右子树的最小高度
int rightDepth = minDepth(root.right);
// 左子树为空
if (root.left == null && root.right != null) {
return rightDepth + 1;
}
// 右子树为空
if (root.right == null && root.left != null) {
return leftDepth + 1;
}
// 左右字数都不为空
return Math.min(leftDepth, rightDepth) + 1;
}
}
222.完全二叉树的节点个数
题目链接
思路:
- 可以通过前中后序 递归遍历来计算出节点个数
递归法:后序
本题说的是完全二叉树 但是现在利用后序遍历就把它看作是一个普通的二叉树 把每个结点都遍历了一遍 时间复杂度:O(n)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int countNodes(TreeNode root) {
if(root == null) {
return 0;
}
// 左+右+根结点本身
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
如果是满二叉树 计算结点个数是通过公式:2^n - 1来计算的(n为深度)——遍历二叉树 当其左子树/右子树是满二叉树时就可以直接用公式计算 在返回给父结点
那么如何判断子树是否是满二叉树?如何求其深度呢?
如果是满二叉树 那么左右遍历的深度是一样的 如果不是满二叉树就一直往后遍历 因为到最后根结点一定会是一个满二叉树
仅仅遍历了两侧的结点树 内侧的结点没有遍历 故减少了时间复杂度
针对完全二叉树:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int countNodes(TreeNode root) {
// 两种终止条件 一个是遇到为空 一个是遇到满二叉树
// 递归到空结点
if(root == null) {
return 0;
}
TreeNode left = root.left;
TreeNode right = root.right;
// 初始为0 方便后面用位运算
int leftDepth = 0, rightDepth = 0;
while (left != null) {
// 求左子树深度 遍历外侧
left = left.left;
leftDepth++;
}
while (right != null) {
// 求右子树深度 遍历外侧
right = right.right;
rightDepth++;
}
// 左右子树深度相等 说明是满二叉树
if (leftDepth == rightDepth) {
// 注意(2<<1) 相当于2^2 所以leftDepth初始为0
return (2 << leftDepth) - 1;
}
// 单层递归的逻辑 左右中 后序精简写
return countNodes(root.left) + countNodes(root.right) + 1;
}
}