# 865. Smallest Subtree with all the Deepest Nodes

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes/description/

> 内容描述

```
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 its subtree.

 

Example 1:

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

![](https://github.com/apachecn/LeetCode/blob/master/images/sketch1.png)

```
We return the node with value 2, colored in yellow in the diagram.
The nodes colored in blue are the deepest nodes of the tree.
The input "[3, 5, 1, 6, 2, 0, 8, null, null, 7, 4]" is a serialization of the given tree.
The output "[2, 7, 4]" is a serialization of the subtree rooted at the node with value 2.
Both the input and output have TreeNode type.

Note:

The number of nodes in the tree will be between 1 and 500.
The values of each node are unique.
```

## 解题方案

> 思路 1

直接参考的[leetcode solution](https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes/solution/)
- 首先将所有的node与其对应的depth记录下来
- 然后，从root开始往下走，如果一个node的depth是最大的depth的话，就直接返回这个node，递归进行
- 如果这个node的depth不是最大的depth，但是它的左孩子和右孩子的depth都最大的话也是直接返回这个node，递归进行

```python
class Solution(object):
    def subtreeWithAllDeepest(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        depth = {
            None: -1
        }
        def dfs(node, parent = None):
            if node:
                depth[node] = depth[parent] + 1
                dfs(node.left, node)
                dfs(node.right, node)
                
        dfs(root)
        max_depth = max(depth.values())
        
        def decide(node):
            if not node or depth[node] == max_depth:
                return node
            l, r = decide(node.left), decide(node.right)
            return node if l and r else l or r
        return decide(root)
```

> 思路 2

The Result (on some subtree) returned by our (depth-first search) recursion will have two parts: 
- Result.node: the largest depth node that is equal to or an ancestor of all the deepest nodes of this subtree. 
- Result.depth: the number of nodes in the path from the root of this subtree, to the deepest node in this subtree.

We can calculate these answers disjointly for dfs(node):

To calculate the Result.node of our answer:

- If one childResult has deeper nodes, then childResult.node will be the answer.

- If they both have the same depth nodes, then node will be the answer.

- The Result.depth of our answer is always 1 more than the largest childResult.depth we have.

```python
class Solution(object):
    def subtreeWithAllDeepest(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        Result = collections.namedtuple('Result', ('node', 'depth'))
        def dfs(node):
            if not node:
                return Result(None, 0)
            l, r = dfs(node.left), dfs(node.right)
            if l.depth > r.depth:
                return Result(l.node, l.depth+1)
            elif l.depth < r.depth:
                return Result(r.node, r.depth+1)
            else:
                return Result(node, l.depth+1)
        return dfs(root).node
```

> 思路 3

自己的解法：

```python
class Solution(object):
    def subtreeWithAllDeepest(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        def depth(node):
            return 0 if not node else max(depth(node.left), depth(node.right)) + 1
        
        tmp = depth(root.left) - depth(root.right)
        if tmp == 0:
            return root
        elif tmp > 0:
            return self.subtreeWithAllDeepest(root.left)
        else:
            return self.subtreeWithAllDeepest(root.right)
```



## Follow up

如果每一个树节点可以拥有超过2个孩子怎么办：

> 思路 1

自己的解法, 
- 只要这个节点的孩子中有两个及以上的depth相等就直接返回这个node本身
- 如果只有一个孩子的depth最大就返回那个孩子

```python
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.children = []
	
	
class Solution(object):
    def subtreeWithAllDeepestForMoreChildren(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        # calculate a node's depth
        def depth(node):
            if not node:
                return 0
            tmp = [depth(child) for child in node.children]
            if not tmp or len(tmp) == 0:
                return 1
            return max(tmp) + 1

        if not root:
            return None
        tmp = [depth(child) for child in root.children]
        if not tmp or len(tmp) == 0:
            return root
        # if 2 or more children have same depth, then return the node itself
        if tmp.count(max(tmp)) > 1:
            return root
        # else recalculate the child who has largest depth
        else:
            return self.subtreeWithAllDeepestForMoreChildren(root.children[tmp.index(max(tmp))])
```

搞一下测试用例

```python
import unittest


class TestSolution(unittest.TestCase):
    def test_1(self):
        root = TreeNode(0)

        for i in range(1, 4):
            root.children.append(TreeNode(i))

        for i in range(4, 10):
            root.children[1].children.append(TreeNode(i))
        self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 2)

    def test_2(self):
        root = TreeNode(0)
        self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 0)

    def test_3(self):
        root = TreeNode(0)

        for i in range(1, 4):
            root.children.append(TreeNode(i))

        for i in range(4, 10):
            root.children[1].children.append(TreeNode(i))

        for i in range(10, 12):
            root.children[2].children.append(TreeNode(i))
        self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 0)

    def test_4(self):
        root = TreeNode(0)

        for i in range(1, 3):
            root.children.append(TreeNode(i))

        for i in range(3, 5):
            root.children[0].children.append(TreeNode(i))

        for i in range(5, 7):
            root.children[1].children.append(TreeNode(i))

        for i in range(7, 9):
            root.children[0].children[1].children.append(TreeNode(i))
        self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 4)

    def test_5(self):
        root = TreeNode(0)

        for i in range(1, 5):
            root.children.append(TreeNode(i))
        root.children[1].children.append(TreeNode(5))
        root.children[2].children.append(TreeNode(6))
        root.children[3].children.append(TreeNode(7))
        self.assertTrue(Solution().subtreeWithAllDeepestForMoreChildren(root).val == 0)


if __name__ == "__main__":
    unittest.main()
	
	
	
.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s

OK
```


> 思路 2



```python
import collections
import sys


class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.children = []


# Find the tree with largest depth among all nodes
class Solution(object):
    def subtreeWithAllDeepestForMoreChildren(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        Result = collections.namedtuple("Result", ("node", "depth"))

        # return the Result of the subtree at this node
        def dfs(node):
            if not node:
                return Result(None, 0)
            if len(node.children) == 0:
                return Result(node, 1)
            largest_depth = 0
            res = Result(None, 0)
            for child in node.children:
                cur = dfs(child)  # cur is a Result type: store ('node','depth')
                if cur.depth > abs(largest_depth):
                    largest_depth = cur.depth
                    res = cur
                elif cur.depth == largest_depth:
                    # negative number means largestDepth occurs more than once
                    largest_depth = -largest_depth
            if largest_depth > 0:
                return Result(res.node, largest_depth + 1)
            return Result(node, -largest_depth + 1)

        return dfs(root).node
```





















