Smallest Subtree with all the Deepest Nodes 具有所有最深结点的最小子树

给定一个根为 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;
}
};

 

点赞