104、二叉树的最大深度
思路:本题的关键是要理解题意,最大深度等价于求根节点的高度,而求节点的高度可以通过后序遍历来实现。
因为后序遍历的顺序是左右中,因此当返回左子树和右子树的高度(递归实现)时,取出其中的最大值并加1就可以了。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getDepth(TreeNode* node){
//传入root
//确定终止条件
if(node==nullptr)return 0;
//想清每层逻辑
int leftDepth=getDepth(node->left);//left
int rightDepth=getDepth(node->right);//right
int Depth=1+max(leftDepth,rightDepth);//middle
return Depth;
}
int maxDepth(TreeNode* root) {
//二叉树的最大深度等价于求根的高度(可以用后序实现)
return getDepth(root);
}
};
111、二叉树的最小深度
思路:本题相当于求根节点到叶子节点的最小高度
分析:本题看上去和二叉树的最大深度很像,都是求树的深度,乍一看差不多,其实是有区别的,首先要明确本题对二叉树最小深度的定义:从根节点到叶子节点的最小距离。因此如果一棵树的左子树非空,右子树为空的话,那么我们不能说这棵树的最小深度是1.
明确这点很重要,因为这直接关系到我们对终止条件的设置。
也就是说,如果一棵子树为空,而另一棵子树非空的话,那么我们不能说遍历到这里就停止了,因为这不符合最小深度的定义,空节点不是叶子节点,我们还要继续在非空的子树上遍历下去才可以。
总结:本题的关键是要理解好最小深度的含义,判断好终止条件,求高度仍然是使用的后序遍历的方法来求解。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getDepth(TreeNode* node){
if(node==nullptr)return 0;
int leftDepth=getDepth(node->left);//left
int rightDepth=getDepth(node->right);//right
//注意求最大深度和这里求最小深度的不同
//当一棵树,左空右不空,此处非最低点
if(node->left==nullptr&&node->right!=nullptr)
return 1+rightDepth;
//当一棵树,左不空右空,此处非最低点
if(node->left!=nullptr&&node->right==nullptr)
return 1+leftDepth;
//左右都不空
return 1+min(leftDepth,rightDepth);
}
int minDepth(TreeNode* root) {
return getDepth(root);
}
};
222、完全二叉树的节点数量
分析:完全二叉树也是二叉树,因此本题当然可以使用统计普通二叉树的方法来求解完全二叉树的节点数量。前中后序遍历,层序遍历等方法都是可以的,但是这些方法并没有对完全二叉树的特性加以利用。
我们来分析一下,对于一棵完全二叉树而言,它除了最后一层可能没有填满之外,其余层一定全都填满了,因此从这个角度出发,假定一棵完全二叉树的高度为h,我们不难算出其前h-1层的节点数目应为2的h-1次方-1.这告诉了我们h-1层的满二叉树它的节点数目的计算公式,由此进一步分析,我们可以发现,如果我们沿着一棵树的最外侧同时向左右两边走,那么如果左右两边走的步数相同,则它必定是一棵满二叉树(注意:这里的树已经是一棵完全二叉树了),因此,我们可以像这样不断通过满二叉树来计算节点的数量(注意一个节点也是一个满二叉树)。
总结:本题的关键是要能够通过遍历树的左右两侧来判断该树是否为满二叉树,进而通过公式计算出满二叉树的节点数量,不断累加从而得到最终结果。这样做可以省去对中间节点的检测,**普通的遍历方式时间复杂度显然是O(N),但是用这种方法那么只需要遍历相当于树高的节点即可完成判断,由于完全二叉树的树高是O(Logn)数量级的,因此总的时间复杂度应该是O(Logn*Logn),**注意这样的时间复杂度仍然比普通遍历有着较大的提升,并且这样是充分利用了完全二叉树的特性的,更符合出题人想法,值得学习。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getNodesNum(TreeNode* cur){
if(cur==nullptr)return 0;
int leftNum=getNodesNum(cur->left);//left
int rightNum=getNodesNum(cur->right);//right
int result=1+leftNum+rightNum;
return result;
}
int countNodes(TreeNode* root) {
return getNodesNum(root);
}
};