class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
List<TreeNode> arr1 = new ArrayList<>();
List<TreeNode> arr2 = new ArrayList<>();
dfs(root,p.val,arr1);
dfs(root,q.val,arr2);
int i = 0;
int j = 0;
//对arr1和arr2进行扫描,直到他们的值不相等,则说明至少找到了p或者q
while(i <= arr1.size() - 1 && j <= arr2.size() - 1){
if(arr1.get(i).val != arr2.get(j).val) break;
i++;
j++;
}
//从 i-1 开始向前扫描,判断p和q是否在子树内,第一个满足条件的就是最近公共祖先。
while(i >= 0) {
if(find(arr1.get(i - 1),p.val) && find(arr1.get(i - 1),q.val)) break;
else i--;
}
return arr1.get(i - 1);
}
//前序遍历二叉树直到找到目标节点
public void dfs(TreeNode node, int val,List<TreeNode> arr){
if(node == null) return;
arr.add(node);
if(node.val == val) return;
dfs(node.left,val,arr);
dfs(node.right,val,arr);
}
//确定val是否在node这颗子树中
public boolean find(TreeNode node, int val){
if(node == null) return false;
if(node.val == val) return true;
return find(node.left,val) || find(node.right,val);
}
}
看了官方题解的两种方法,一种递归,运行时间短,另一种储存父节点,他们都遍历了整个二叉树空间复杂度略高,其他都很秀。我的方法没有遍历整个二叉树,前序遍历找到节点就终止了,然后向前扫子树都存在p和q,就直接返回。