题目描述
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
题目说明
此题与二叉树的遍历有关,关于二叉树的三种遍历方法的实现参考下面这篇博客,大佬写得很详细
C++实现二叉树 前、中、后序遍历(递归与非递归)非递归实现过程最简洁版本
此题可用的两种解法,分别对应二叉树的两种遍历方法,即循环遍历和递归遍历。
解法1:循环法
记录每个结点的深度,与当前的最大深度作比较,不断更新最大深度
int maxDepth(TreeNode* root) {
stack<pair<TreeNode*, int>> s;
TreeNode* p = root;
int depth = 0;
int maxDepth = 0;
while(p!=NULL || !s.empty()) // 若栈非空,则说明还有一些节点的右子树尚未探索;若p非空,意味着还有一些节点的左子树尚未探索
{
while(p!=NULL) // 优先往左边走,次循环作用是先记录当前结点的深度信息和结点地址,再走左支路
{
s.push(pair<TreeNode*, int> (p, ++depth));
p = p->left;
}
//if(!s.empty())
if(1)
{
p = s.top().first; // 若左边无路,就预备右拐。右拐之前,记录右拐点的基本信息
depth = s.top().second;
maxDepth = depth>maxDepth?depth:maxDepth; // 预备右拐时,比较当前节点深度和之前存储的最大深度
s.pop(); // 将右拐点出栈;此时栈顶为右拐点的前一个结点。在右拐点的右子树全被遍历完后,会预备在这个节点右拐
p = p->right;
}
}
return maxDepth;
}
};
由循环法前序遍历而来,循环法前序遍历代码如下:
void preorderTraversal(TreeNode *root, vector<int> &path)
{
stack<TreeNode *> s;
TreeNode *p = root;
while(p != NULL || !s.empty())
{
while(p != NULL) // 先循环遍历左结点,直到左分支是NULL,即不存在左结点
{
path.push_back(p->val);
s.push(p);
p = p->left;
}
if(!s.empty()) // 一直感觉这句判断可有可无,到时候验证下
{
// 当向左分支走不下去的时候(走到向左的分支发现结点是NULL),返回上层结点,走向右分支
p = s.top();
s.pop();
p = p->right;
}
}
}
解法2:递归法
递归法实现起来要相对简单,但不是很好理解,意思是每一次调用函数都比较两个支路各自所具有的深度,然后返回深度较大的一路。
int maxDepth(TreeNode* root) {
if(root == NULL) return 0;
int l = maxDepth(root->left) + 1;
int r = maxDepth(root->right) + 1;
return l>r?l:r;
}
由递归法前序遍历而来,递归法前序遍历代码如下:
void preorderTraversal(TreeNode *root, vector<int> &path)
{
if(root != NULL)
{
path.push_back(root->val);
preorderTraversal(root->left, path);
preorderTraversal(root->right, path);
}
}