给定一个根为 root
的二叉树,每个结点的深度是它到根的最短距离。
如果一个结点在整个树的任意结点之间具有最大的深度,则该结点是最深的。
一个结点的子树是该结点加上它的所有后代的集合。
返回能满足“以该结点为根的子树中包含所有最深的结点”这一条件的具有最大深度的结点。
示例:
输入:[3,5,1,6,2,0,8,null,null,7,4] 输出:[2,7,4] 解释: 我们返回值为 2 的结点,在图中用黄色标记。 在图中用蓝色标记的是树的最深的结点。 输入 "[3, 5, 1, 6, 2, 0, 8, null, null, 7, 4]" 是对给定的树的序列化表述。 输出 "[2, 7, 4]" 是对根结点的值为 2 的子树的序列化表述。 输入和输出都具有 TreeNode 类型。
提示:
- 树中结点的数量介于 1 和 500 之间。
- 每个结点的值都是独一无二的。
思路:这道题一开始的思路是找到最左叶子结点和最右叶子结点,然后求最近公共祖先节点,然后发现代码写的很冗余也很难,放弃了。。。然后看discuss部分,简直方法巧到妙。。。不看答案是不可能写出来的,这辈子都不可能的。。。
言归正传,我们只需要一个辅助函数deep(TreeNode* root),deep的返回值是pair<int,TreeNode*>,其中int存储深度信息,TreeNode*存储节点信息。deep函数内部如下伪代码所示:
如果root为空,返回{0,nullptr} //意味着空节点的深度为0
然后递归调用左右子节点deep函数,l=deep(root->left),r=deep(root->right)
如果l.first==r.first即左右孩子节点的深度一样,那么应该返回当前节点且深度加1,即return {l.first+1,root}
如果l.first>r.first即左子树的深度大于右子树的深度,那么最深的节点只会在左子树出现,所以返回左子树,即return {l.first+1,l.second}
如果l.first>r.first即右子树的深度大于左子树的深度,那么最深的节点只会在右子树出现,所以返回右子树,即return {r.first+1,r.second}
最后主函数调用deep函数,返回deep(root).second即可。
参考代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
pair<int, TreeNode*> deep(TreeNode* root) {
if (!root) return { 0,nullptr };
auto l = deep(root->left), r = deep(root->right);
return { max(l.first,r.first) + 1,l.first == r.first ? root : l.first > r.first ? l.second : r.second };
}
TreeNode* subtreeWithAllDeepest(TreeNode* root) {
return deep(root).second;
}
};