866. Smallest Subtree with all the Deepest Nodes

Given a binary tree rooted at root, the depth of each node is the shortest distance to the root.

A node is deepest if it has the largest depth possible among any node in the entire tree.

The subtree of a node is that node, plus the set of all descendants of that node.

Return the node with the largest depth such that it contains all the deepest nodes in it's subtree.

Input: [3,5,1,6,2,0,8,null,null,7,4]
Output: [2,7,4]

这道题的意思是:

有一个二叉树,每一个节点到根的距离,就是深度,其中就有深度最大的那一个或几个节点。

要求返回这些深度最大的节点的最小公共祖先。

我的解法是用深度优先遍历二叉树,保存最长的一条或几条路径。遍历完成后,自底向上找第一个相同的节点。

这个解法的好处是只需要遍历一遍二叉树,但是除了递归以外,还牺牲了一点空间。

另外,如果路径特别长,在最后查找节点时,可能费点时间。

 1 class Solution {
 2 private:
 3     void dfs(TreeNode* root, vector<vector<TreeNode*>> &path, vector<TreeNode*> &p, int &depth) {
 4         p.push_back(root);
 5         if (root->left || root->right) {
 6             if (root->left)
 7                 dfs(root->left, path, p, depth);
 8             if (root->right)
 9                 dfs(root->right, path, p, depth);
10         }
11         else {
12             if (p.size() > depth) {
13                 depth = p.size();
14                 path.clear();
15                 path.push_back(p);
16             }
17             else if (p.size() == depth)
18                 path.push_back(p);
19             else;
20         }
21         p.pop_back();
22     }
23 public:
24     TreeNode* subtreeWithAllDeepest(TreeNode* root) {
25         vector<vector<TreeNode*>> path;
26         vector<TreeNode*> single_path;
27         int depth = 0;
28         dfs(root, path, single_path, depth);
29         TreeNode* flag;
30         for (int j = depth - 1; j >= 0; --j) {
31             flag = path[0][j];
32             int i = 1;
33             for (i = 1; i < path.size(); ++i) {
34                 if (path[i][j] != flag)
35                     break;
36             }
37             if (i == path.size())
38                 return flag;
39         }
40     }
41 };

另外还有一种解法,思路是对于每个节点,求其左右子树的深度。如果左右子树的深度一样,那么左右子树中都存在最大深度叶节点,这个节点就是最小公共祖先。

如果不一样的话,就从找深度比较大的那个子树里去找。

这个解法的好处是,除了递归以外,不需要其他空间,但是可能存在重复遍历二叉树的问题。另外,代码非常简洁。

 1 class Solution {
 2 private:
 3     int depth(TreeNode* root) {
 4         if (!root)
 5             return 0;
 6         int l = depth(root->left);
 7         int r = depth(root->right);
 8         return 1 + max(l, r);
 9     }
10 public:
11     TreeNode* subtreeWithAllDeepest(TreeNode* root) {
12         int l = depth(root->left);
13         int r = depth(root->right);
14         if (l == r)
15             return root;
16         if (l > r)
17             return subtreeWithAllDeepest(root->left);
18         else
19             return subtreeWithAllDeepest(root->right);
20     }
21 };

综上,上述两种解法,时间上,第一种在答案比较靠近叶节点时效果较好,第二种在答案比较靠近根节点时效果非常好。

猜你喜欢

转载自www.cnblogs.com/Zzz-y/p/9290120.html