130 lines
4.2 KiB
Markdown
130 lines
4.2 KiB
Markdown
|
## 题目地址
|
|||
|
|
|||
|
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/
|
|||
|
|
|||
|
## 题目描述
|
|||
|
|
|||
|
```
|
|||
|
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
|
|||
|
|
|||
|
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
|
|||
|
|
|||
|
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
|
|||
|
|
|||
|
```
|
|||
|
![236.lowest-common-ancestor-of-a-binary-tree](../assets/problems/236.lowest-common-ancestor-of-a-binary-tree-1.png)
|
|||
|
|
|||
|
```
|
|||
|
Example 1:
|
|||
|
|
|||
|
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
|
|||
|
Output: 3
|
|||
|
Explanation: The LCA of nodes 5 and 1 is 3.
|
|||
|
Example 2:
|
|||
|
|
|||
|
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
|
|||
|
Output: 5
|
|||
|
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
|
|||
|
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
All of the nodes' values will be unique.
|
|||
|
p and q are different and both values will exist in the binary tree.
|
|||
|
```
|
|||
|
|
|||
|
## 思路
|
|||
|
|
|||
|
这道题目是求解二叉树中,两个给定节点的最近的公共祖先。是一道非常经典的二叉树题目。
|
|||
|
|
|||
|
我们之前说过树是一种递归的数据结构,因此使用递归方法解决二叉树问题从写法上来看是最简单的,这道题目也不例外。
|
|||
|
|
|||
|
用递归的思路去思考树是一种非常重要的能力。
|
|||
|
|
|||
|
|
|||
|
如果大家这样去思考的话,问题就会得到简化,我们的目标就是分别在左右子树进行查找p和q。 如果p没有在左子树,那么它一定在右子树(题目限定p一定在树中),
|
|||
|
反之亦然。
|
|||
|
|
|||
|
对于具体的代码而言就是,我们假设这个树就一个结构,然后尝试去解决,然后在适当地方去递归自身即可。 如下图所示:
|
|||
|
|
|||
|
![236.lowest-common-ancestor-of-a-binary-tree-2](../assets/problems/236.lowest-common-ancestor-of-a-binary-tree-2.png)
|
|||
|
|
|||
|
我们来看下核心代码:
|
|||
|
|
|||
|
```js
|
|||
|
// 如果我们找到了p,直接进行返回,那如果下面就是q呢? 其实这没有影响,但是还是要多考虑一下
|
|||
|
if (!root || root === p || root === q) return root;
|
|||
|
const left = lowestCommonAncestor(root.left, p, q); // 去左边找,我们期望返回找到的节点
|
|||
|
const right = lowestCommonAncestor(root.right, p, q);// 去右边找,我们期望返回找到的节点
|
|||
|
if (!left) return right; // 左子树找不到,返回右子树
|
|||
|
if (!right) return left; // 右子树找不到,返回左子树
|
|||
|
return root; // 左右子树分别有一个,则返回root
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
> 如果没有明白的话,请多花时间消化一下
|
|||
|
|
|||
|
## 关键点解析
|
|||
|
|
|||
|
- 用递归的思路去思考树
|
|||
|
|
|||
|
## 代码
|
|||
|
|
|||
|
代码支持: JavaScript, Python3
|
|||
|
|
|||
|
- JavaScript Code:
|
|||
|
|
|||
|
```js
|
|||
|
/**
|
|||
|
* Definition for a binary tree node.
|
|||
|
* function TreeNode(val) {
|
|||
|
* this.val = val;
|
|||
|
* this.left = this.right = null;
|
|||
|
* }
|
|||
|
*/
|
|||
|
/**
|
|||
|
* @param {TreeNode} root
|
|||
|
* @param {TreeNode} p
|
|||
|
* @param {TreeNode} q
|
|||
|
* @return {TreeNode}
|
|||
|
*/
|
|||
|
var lowestCommonAncestor = function(root, p, q) {
|
|||
|
if (!root || root === p || root === q) return root;
|
|||
|
const left = lowestCommonAncestor(root.left, p, q);
|
|||
|
const right = lowestCommonAncestor(root.right, p, q);
|
|||
|
if (!left) return right; // 左子树找不到,返回右子树
|
|||
|
if (!right) return left; // 右子树找不到,返回左子树
|
|||
|
return root; // 左右子树分别有一个,则返回root
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
- Python Code:
|
|||
|
|
|||
|
``` python
|
|||
|
# Definition for a binary tree node.
|
|||
|
# class TreeNode:
|
|||
|
# def __init__(self, x):
|
|||
|
# self.val = x
|
|||
|
# self.left = None
|
|||
|
# self.right = None
|
|||
|
|
|||
|
class Solution:
|
|||
|
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
|
|||
|
if not root or root == p or root == q:
|
|||
|
return root
|
|||
|
left = self.lowestCommonAncestor(root.left, p, q)
|
|||
|
right = self.lowestCommonAncestor(root.right, p, q)
|
|||
|
|
|||
|
if not left:
|
|||
|
return right
|
|||
|
if not right:
|
|||
|
return left
|
|||
|
else:
|
|||
|
return root
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
## 扩展
|
|||
|
如果递归的结束条件改为`if (!root || root.left === p || root.right === q) return root;` 代表的是什么意思,对结果有什么样的影响?
|
|||
|
|