剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

85 阅读1分钟

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

1、递归法

  1. if (!root) return null是递归出口
  2. 根节点值都大于两个数,很明显p q的老爹在左子树里面,则遍历左子树
  3. 根节点值都小于两个数,很明显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、循环赋值法

  1. 遍历根节点,如果p和q的值都大于根节点,则root = root.right将视角锁定在root.right上,以它为根节点继续遍历判断
  2. 左边节点同理
  3. 如果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;
    }
  }
};