来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

解答

比较傻的办法,性能也比较差:
使用层级遍历的方法,先把父节点都收集起来,然后比较两个数组

  1. var lowestCommonAncestor = function(root, p, q) {
  2. let stack = [ root ];
  3. root.parents = [ root ];
  4. while (stack.length) {
  5. let temp = [];
  6. for (let item of stack) {
  7. if (item) {
  8. const leftNode = item?.left;
  9. if (leftNode) {
  10. leftNode.parents = [...item.parents, leftNode];
  11. temp.push(leftNode);
  12. }
  13. const rightNode = item?.right;
  14. if (rightNode) {
  15. rightNode.parents = [...item.parents, rightNode];
  16. temp.push(rightNode);
  17. }
  18. }
  19. }
  20. stack = temp;
  21. }
  22. let pParents = p.parents;
  23. let qParents = q.parents;
  24. let startIndex = 0;
  25. while (pParents[startIndex] && pParents[startIndex] === qParents[startIndex]) {
  26. startIndex++;
  27. }
  28. return pParents[startIndex - 1];
  29. };

优化

  1. 可以使用递归,递归中 return 使用 或||,因为走左还是走右不确定,只有匹配到才返回数组,否则碰到 null 则返回 null
  2. 两个数组的比对,从后往前,碰到另一个数组中没有的则中断并返回

    1. var lowestCommonAncestor = function(root, p, q) {
    2. function dfs (node, target, selected) {
    3. if (node === target) {
    4. return [...selected, node];
    5. }
    6. if (node === null) {
    7. return null;
    8. }
    9. return dfs(node.left, target, [...selected, node]) || dfs(node.right, target, [...selected, node]);
    10. }
    11. let pParents = dfs(root, p, []);
    12. let qParents = dfs(root, q, []);
    13. for (let i = pParents.length - 1; i >= 0; i--) {
    14. if (~qParents.indexOf(pParents[i])) {
    15. return pParents[i];
    16. }
    17. }
    18. };