Skip to content

Commit 9ca9ece

Browse files
authored
Update 剑指offer面试题68--树中两个结点的最低公共祖先.md
1 parent 7099f72 commit 9ca9ece

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

notes/剑指offer面试题68--树中两个结点的最低公共祖先.md

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ public class LastSameInTreeParent {
103103

104104
```
105105

106-
## 普通树,没有指向父结点的指针
106+
## 普通二叉树,没有指向父结点的指针
107107

108-
这道题再加大难度,如果没有指向父结点的指针呢?是否还能转换成两个链表的第一个公共结点来解决?
108+
这道题再加大难度,如果没有指向父结点的指针呢?
109109

110110
想办法创造链表。两个输入结点如果在树中存在,那么**从根结点开始向下的某条路径中必然包含这个结点**,使用两个链表分别保存包含这两个结点的路径。这样就可以把问题转换成求两个链表的第一个公共结点了。
111111

@@ -130,23 +130,28 @@ public class LastSameInTree {
130130

131131
LinkedList<Node> path1 = new LinkedList<>();
132132
LinkedList<Node> path2 = new LinkedList<>();
133-
collectNode(root, a, path1);
134-
collectNode(root, b, path2);
133+
134+
LinkedList<Node> res1 = new LinkedList<>();
135+
LinkedList<Node> res2 = new LinkedList<>();
136+
collectNode(root, a, path1, res1);
137+
collectNode(root, b, path2, res2);
135138
return getLastSameNode(path1, path2);
136139
}
137140

138141
/**
139142
* 收集含有结点node的路径上的所有结点,形成一条链表
140143
*/
141-
private boolean collectNode(Node root, Node node, LinkedList<Node> path) {
142-
if (root == node) return true;
144+
private void collectNode(Node root, Node node, LinkedList<Node> path, LinkedList<Node> res) {
145+
if (root == null || node == null) return;
143146
path.add(root);
147+
if (root = node) {
148+
res.addAll(path);
149+
}
144150
for (Node child : root.children) {
145-
if (collectNode(child, node, path)) return true;
151+
if (collectNode(child, node, path));
146152
}
147153
// 该条路径上没找到结点node就要从路径中移除
148-
path.removeLast();
149-
return false;
154+
path.remove(path.size() - 1);
150155
}
151156

152157
/**
@@ -172,6 +177,25 @@ public class LastSameInTree {
172177

173178
---
174179

180+
181+
普通二叉树的递归解法
182+
183+
来自[LeetCode](https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/)
184+
185+
```java
186+
class Solution {
187+
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
188+
if(root == null) return null; // 如果树为空,直接返回null
189+
if(root == p || root == q) return root; // 如果 p和q中有等于 root的,那么它们的最近公共祖先即为root(一个节点也可以是它自己的祖先)
190+
TreeNode left = lowestCommonAncestor(root.left, p, q); // 递归遍历左子树,只要在左子树中找到了p或q,则先找到谁就返回谁
191+
TreeNode right = lowestCommonAncestor(root.right, p, q); // 递归遍历右子树,只要在右子树中找到了p或q,则先找到谁就返回谁
192+
if(left == null) return right; // 如果在左子树中 p和 q都找不到,则 p和 q一定都在右子树中,右子树中先遍历到的那个就是最近公共祖先(一个节点也可以是它自己的祖先)
193+
else if(right == null) return left; // 否则,如果 left不为空,在左子树中有找到节点(p或q),这时候要再判断一下右子树中的情况,如果在右子树中,p和q都找不到,则 p和q一定都在左子树中,左子树中先遍历到的那个就是最近公共祖先(一个节点也可以是它自己的祖先)
194+
else return root; //否则,当 left和 right均不为空时,说明 p、q节点分别在 root异侧, 最近公共祖先即为 root
195+
}
196+
}
197+
```
198+
175199
by @sunhaiyu
176200

177201
2018.2.14

0 commit comments

Comments
 (0)