1、递归法
if (!root) return null是递归出口- 根节点值都大于两个数,很明显p q的老爹在左子树里面,则遍历左子树
- 根节点值都小于两个数,很明显p q的老爹在右子树里面,则遍历右子树
const lowestCommonAncestor = (root, p, q) => {
if (!root) return null;
if (root.val > p.val && root.val > q.val) {
return lowestCommonAncestor(root.left, p, q);
}
if (root.val < p.val && root.val < q.val) {
return lowestCommonAncestor(root.right, p, q);
}
return root;
};
2、循环赋值法
- 遍历根节点,如果p和q的值都大于根节点,则root = root.right将视角锁定在root.right上,以它为根节点继续遍历判断
- 左边节点同理
- 如果p.val 和 q.val 一个大于root.val 一个小于root.val,则说明此时root才是p和q的最大的根
这里有个漏洞就是,最近公共祖先节点可以为节点本,于是当p和q是同一个节点,则直接返回p或者q就行
const lowestCommonAncestor = (root, p, q) => {
if (!root) return null;
if (p.val === q.val) return p;
while (root) {
// 当前节点值在p,q的左边,遍历右子树
if (root.val < q.val && root.val < p.val) {
root = root.right;
} else if (root.val > q.val && root.val > p.val) {
// 当前节点值在p,q的右边,遍历左子树
root = root.left;
} else {
// 当前节点值在p,q的中间,那么当前节点就是公共祖先
return root;
}
}
};