Skip to content

Commit 5af8967

Browse files
authored
feat: add solutions to lc problem: No.0236 (#2328)
No.0236.Lowest Common Ancestor of a Binary Tree
1 parent bb202c6 commit 5af8967

File tree

9 files changed

+175
-178
lines changed

9 files changed

+175
-178
lines changed

solution/0200-0299/0236.Lowest Common Ancestor of a Binary Tree/README.md

+58-65
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,13 @@
5151

5252
### 方法一:递归
5353

54-
根据“**最近公共祖先**”的定义,若 root 是 p, q 的最近公共祖先 ,则只可能为以下情况之一
54+
我们递归遍历二叉树
5555

56-
- 如果 p 和 q 分别是 root 的左右节点,那么 root 就是我们要找的最近公共祖先;
57-
- 如果 p 和 q 都是 root 的左节点,那么返回 `lowestCommonAncestor(root.left, p, q)`
58-
- 如果 p 和 q 都是 root 的右节点,那么返回 `lowestCommonAncestor(root.right, p, q)`
56+
如果当前节点为空或者等于 $p$ 或者 $q$,则返回当前节点;
5957

60-
**边界条件讨论**
58+
否则,我们递归遍历左右子树,将返回的结果分别记为 $left$ 和 $right$。如果 $left$ 和 $right$ 都不为空,则说明 $p$ 和 $q$ 分别在左右子树中,因此当前节点即为最近公共祖先;如果 $left$ 和 $right$ 中只有一个不为空,返回不为空的那个。
6159

62-
- 如果 root 为 null,则说明我们已经找到最底了,返回 null 表示没找到;
63-
- 如果 root 与 p 相等或者与 q 相等,则返回 root;
64-
- 如果左子树没找到,递归函数返回 null,证明 p 和 q 同在 root 的右侧,那么最终的公共祖先就是右子树找到的结点;
65-
- 如果右子树没找到,递归函数返回 null,证明 p 和 q 同在 root 的左侧,那么最终的公共祖先就是左子树找到的结点。
60+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树节点个数。
6661

6762
<!-- tabs:start -->
6863

@@ -77,9 +72,9 @@
7772

7873
class Solution:
7974
def lowestCommonAncestor(
80-
self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'
81-
) -> 'TreeNode':
82-
if root is None or root == p or root == q:
75+
self, root: "TreeNode", p: "TreeNode", q: "TreeNode"
76+
) -> "TreeNode":
77+
if root in (None, p, q):
8378
return root
8479
left = self.lowestCommonAncestor(root.left, p, q)
8580
right = self.lowestCommonAncestor(root.right, p, q)
@@ -98,12 +93,15 @@ class Solution:
9893
*/
9994
class Solution {
10095
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
101-
if (root == null || root == p || root == q) return root;
102-
TreeNode left = lowestCommonAncestor(root.left, p, q);
103-
TreeNode right = lowestCommonAncestor(root.right, p, q);
104-
if (left == null) return right;
105-
if (right == null) return left;
106-
return root;
96+
if (root == null || root == p || root == q) {
97+
return root;
98+
}
99+
var left = lowestCommonAncestor(root.left, p, q);
100+
var right = lowestCommonAncestor(root.right, p, q);
101+
if (left != null && right != null) {
102+
return root;
103+
}
104+
return left == null ? right : left;
107105
}
108106
}
109107
```
@@ -121,10 +119,14 @@ class Solution {
121119
class Solution {
122120
public:
123121
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
124-
if (!root || root == p || root == q) return root;
125-
TreeNode* left = lowestCommonAncestor(root->left, p, q);
126-
TreeNode* right = lowestCommonAncestor(root->right, p, q);
127-
if (left && right) return root;
122+
if (root == nullptr || root == p || root == q) {
123+
return root;
124+
}
125+
auto left = lowestCommonAncestor(root->left, p, q);
126+
auto right = lowestCommonAncestor(root->right, p, q);
127+
if (left && right) {
128+
return root;
129+
}
128130
return left ? left : right;
129131
}
130132
};
@@ -145,13 +147,13 @@ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
145147
}
146148
left := lowestCommonAncestor(root.Left, p, q)
147149
right := lowestCommonAncestor(root.Right, p, q)
148-
if left == nil {
149-
return right
150+
if left != nil && right != nil {
151+
return root
150152
}
151-
if right == nil {
153+
if left != nil {
152154
return left
153155
}
154-
return root
156+
return right
155157
}
156158
```
157159

@@ -175,21 +177,12 @@ function lowestCommonAncestor(
175177
p: TreeNode | null,
176178
q: TreeNode | null,
177179
): TreeNode | null {
178-
const find = (root: TreeNode | null) => {
179-
if (root == null || root == p || root == q) {
180-
return root;
181-
}
182-
const left = find(root.left);
183-
const right = find(root.right);
184-
if (left != null && right != null) {
185-
return root;
186-
}
187-
if (left != null) {
188-
return left;
189-
}
190-
return right;
191-
};
192-
return find(root);
180+
if (!root || root === p || root === q) {
181+
return root;
182+
}
183+
const left = lowestCommonAncestor(root.left, p, q);
184+
const right = lowestCommonAncestor(root.right, p, q);
185+
return left && right ? root : left || right;
193186
}
194187
```
195188

@@ -215,31 +208,31 @@ function lowestCommonAncestor(
215208
use std::rc::Rc;
216209
use std::cell::RefCell;
217210
impl Solution {
218-
fn find(
219-
root: &Option<Rc<RefCell<TreeNode>>>,
220-
p: &Option<Rc<RefCell<TreeNode>>>,
221-
q: &Option<Rc<RefCell<TreeNode>>>
222-
) -> Option<Rc<RefCell<TreeNode>>> {
223-
if root.is_none() || root == p || root == q {
224-
return root.clone();
225-
}
226-
let node = root.as_ref().unwrap().borrow();
227-
let left = Self::find(&node.left, p, q);
228-
let right = Self::find(&node.right, p, q);
229-
match (left.is_some(), right.is_some()) {
230-
(true, false) => left,
231-
(false, true) => right,
232-
(false, false) => None,
233-
(true, true) => root.clone(),
234-
}
235-
}
236-
237211
pub fn lowest_common_ancestor(
238212
root: Option<Rc<RefCell<TreeNode>>>,
239213
p: Option<Rc<RefCell<TreeNode>>>,
240214
q: Option<Rc<RefCell<TreeNode>>>
241215
) -> Option<Rc<RefCell<TreeNode>>> {
242-
Self::find(&root, &p, &q)
216+
if root.is_none() || root == p || root == q {
217+
return root;
218+
}
219+
let left = Self::lowest_common_ancestor(
220+
root.as_ref().unwrap().borrow().left.clone(),
221+
p.clone(),
222+
q.clone()
223+
);
224+
let right = Self::lowest_common_ancestor(
225+
root.as_ref().unwrap().borrow().right.clone(),
226+
p.clone(),
227+
q.clone()
228+
);
229+
if left.is_some() && right.is_some() {
230+
return root;
231+
}
232+
if left.is_none() {
233+
return right;
234+
}
235+
return left;
243236
}
244237
}
245238
```
@@ -259,12 +252,12 @@ impl Solution {
259252
* @return {TreeNode}
260253
*/
261254
var lowestCommonAncestor = function (root, p, q) {
262-
if (!root || root == p || root == q) return root;
255+
if (!root || root === p || root === q) {
256+
return root;
257+
}
263258
const left = lowestCommonAncestor(root.left, p, q);
264259
const right = lowestCommonAncestor(root.right, p, q);
265-
if (!left) return right;
266-
if (!right) return left;
267-
return root;
260+
return left && right ? root : left || right;
268261
};
269262
```
270263

solution/0200-0299/0236.Lowest Common Ancestor of a Binary Tree/README_EN.md

+63-57
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,15 @@
4545

4646
## Solutions
4747

48-
### Solution 1
48+
### Solution 1: Recursion
49+
50+
We recursively traverse the binary tree:
51+
52+
If the current node is null or equals to $p$ or $q$, then we return the current node;
53+
54+
Otherwise, we recursively traverse the left and right subtrees, and record the returned results as $left$ and $right$. If both $left$ and $right$ are not null, it means that $p$ and $q$ are in the left and right subtrees respectively, so the current node is the nearest common ancestor; If only one of $left$ and $right$ is not null, we return the one that is not null.
55+
56+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree.
4957

5058
<!-- tabs:start -->
5159

@@ -60,9 +68,9 @@
6068

6169
class Solution:
6270
def lowestCommonAncestor(
63-
self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'
64-
) -> 'TreeNode':
65-
if root is None or root == p or root == q:
71+
self, root: "TreeNode", p: "TreeNode", q: "TreeNode"
72+
) -> "TreeNode":
73+
if root in (None, p, q):
6674
return root
6775
left = self.lowestCommonAncestor(root.left, p, q)
6876
right = self.lowestCommonAncestor(root.right, p, q)
@@ -81,12 +89,15 @@ class Solution:
8189
*/
8290
class Solution {
8391
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
84-
if (root == null || root == p || root == q) return root;
85-
TreeNode left = lowestCommonAncestor(root.left, p, q);
86-
TreeNode right = lowestCommonAncestor(root.right, p, q);
87-
if (left == null) return right;
88-
if (right == null) return left;
89-
return root;
92+
if (root == null || root == p || root == q) {
93+
return root;
94+
}
95+
var left = lowestCommonAncestor(root.left, p, q);
96+
var right = lowestCommonAncestor(root.right, p, q);
97+
if (left != null && right != null) {
98+
return root;
99+
}
100+
return left == null ? right : left;
90101
}
91102
}
92103
```
@@ -104,10 +115,14 @@ class Solution {
104115
class Solution {
105116
public:
106117
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
107-
if (!root || root == p || root == q) return root;
108-
TreeNode* left = lowestCommonAncestor(root->left, p, q);
109-
TreeNode* right = lowestCommonAncestor(root->right, p, q);
110-
if (left && right) return root;
118+
if (root == nullptr || root == p || root == q) {
119+
return root;
120+
}
121+
auto left = lowestCommonAncestor(root->left, p, q);
122+
auto right = lowestCommonAncestor(root->right, p, q);
123+
if (left && right) {
124+
return root;
125+
}
111126
return left ? left : right;
112127
}
113128
};
@@ -128,13 +143,13 @@ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
128143
}
129144
left := lowestCommonAncestor(root.Left, p, q)
130145
right := lowestCommonAncestor(root.Right, p, q)
131-
if left == nil {
132-
return right
146+
if left != nil && right != nil {
147+
return root
133148
}
134-
if right == nil {
149+
if left != nil {
135150
return left
136151
}
137-
return root
152+
return right
138153
}
139154
```
140155

@@ -158,21 +173,12 @@ function lowestCommonAncestor(
158173
p: TreeNode | null,
159174
q: TreeNode | null,
160175
): TreeNode | null {
161-
const find = (root: TreeNode | null) => {
162-
if (root == null || root == p || root == q) {
163-
return root;
164-
}
165-
const left = find(root.left);
166-
const right = find(root.right);
167-
if (left != null && right != null) {
168-
return root;
169-
}
170-
if (left != null) {
171-
return left;
172-
}
173-
return right;
174-
};
175-
return find(root);
176+
if (!root || root === p || root === q) {
177+
return root;
178+
}
179+
const left = lowestCommonAncestor(root.left, p, q);
180+
const right = lowestCommonAncestor(root.right, p, q);
181+
return left && right ? root : left || right;
176182
}
177183
```
178184

@@ -198,31 +204,31 @@ function lowestCommonAncestor(
198204
use std::rc::Rc;
199205
use std::cell::RefCell;
200206
impl Solution {
201-
fn find(
202-
root: &Option<Rc<RefCell<TreeNode>>>,
203-
p: &Option<Rc<RefCell<TreeNode>>>,
204-
q: &Option<Rc<RefCell<TreeNode>>>
205-
) -> Option<Rc<RefCell<TreeNode>>> {
206-
if root.is_none() || root == p || root == q {
207-
return root.clone();
208-
}
209-
let node = root.as_ref().unwrap().borrow();
210-
let left = Self::find(&node.left, p, q);
211-
let right = Self::find(&node.right, p, q);
212-
match (left.is_some(), right.is_some()) {
213-
(true, false) => left,
214-
(false, true) => right,
215-
(false, false) => None,
216-
(true, true) => root.clone(),
217-
}
218-
}
219-
220207
pub fn lowest_common_ancestor(
221208
root: Option<Rc<RefCell<TreeNode>>>,
222209
p: Option<Rc<RefCell<TreeNode>>>,
223210
q: Option<Rc<RefCell<TreeNode>>>
224211
) -> Option<Rc<RefCell<TreeNode>>> {
225-
Self::find(&root, &p, &q)
212+
if root.is_none() || root == p || root == q {
213+
return root;
214+
}
215+
let left = Self::lowest_common_ancestor(
216+
root.as_ref().unwrap().borrow().left.clone(),
217+
p.clone(),
218+
q.clone()
219+
);
220+
let right = Self::lowest_common_ancestor(
221+
root.as_ref().unwrap().borrow().right.clone(),
222+
p.clone(),
223+
q.clone()
224+
);
225+
if left.is_some() && right.is_some() {
226+
return root;
227+
}
228+
if left.is_none() {
229+
return right;
230+
}
231+
return left;
226232
}
227233
}
228234
```
@@ -242,12 +248,12 @@ impl Solution {
242248
* @return {TreeNode}
243249
*/
244250
var lowestCommonAncestor = function (root, p, q) {
245-
if (!root || root == p || root == q) return root;
251+
if (!root || root === p || root === q) {
252+
return root;
253+
}
246254
const left = lowestCommonAncestor(root.left, p, q);
247255
const right = lowestCommonAncestor(root.right, p, q);
248-
if (!left) return right;
249-
if (!right) return left;
250-
return root;
256+
return left && right ? root : left || right;
251257
};
252258
```
253259

solution/0200-0299/0236.Lowest Common Ancestor of a Binary Tree/Solution.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
class Solution {
1111
public:
1212
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
13-
if (!root || root == p || root == q) return root;
14-
TreeNode* left = lowestCommonAncestor(root->left, p, q);
15-
TreeNode* right = lowestCommonAncestor(root->right, p, q);
16-
if (left && right) return root;
13+
if (root == nullptr || root == p || root == q) {
14+
return root;
15+
}
16+
auto left = lowestCommonAncestor(root->left, p, q);
17+
auto right = lowestCommonAncestor(root->right, p, q);
18+
if (left && right) {
19+
return root;
20+
}
1721
return left ? left : right;
1822
}
1923
};

0 commit comments

Comments
 (0)