[路飞]_leetcode-剑指 Offer 68 - I-二叉搜索树的最近公共祖先

466 阅读2分钟

[题目地址] [B站地址]

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

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

例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

解题思路

  1. 遍历二叉搜索树,获取从根节点到两个目标节点的的路径节点数组
  2. 从后向前遍历长度更短的路径数组,直到找到一个节点同时出现在另一个路径数组中,该节点就是最近的公共祖先节点

动画演示

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

代码实现

var lowestCommonAncestor = function(root, p, q) {
  let list1,list2;
  // 遍历二叉树查找目标节点并记录根节点到目标节点的路径
  function preorder(node,list){
    if(node === null) return;
    list.push(node);
    if(node === p){
      list1 = list;
      if(list2) return;
    }
    if(node === q){
      list2 = list;
      if(list1) return;
    }
    // 根据二叉搜索树的性质,减小查找范围
    if((!list1&&p.val<node.val)||(!list2&&q.val<node.val)){
      preorder(node.left,[...list])
    }
    if((!list1&&p.val>node.val)||(!list2&&q.val>node.val)){
      preorder(node.right,[...list])
    }
  }
  preorder(root,[])

  // 从后向前遍历长度更短的路径数组,第一个在另一个路径数组同时存在的节点即为最近的公共祖先节点
  if(list1.length<list2.length){
    for(let i = list1.length-1;i>=0;i--){
      if(list2.indexOf(list1[i])>-1) return list1[i]
    }
  }
  for(let i = list2.length-1;i>=0;i--){
    if(list1.indexOf(list2[i])>-1) return list2[i]
  }
};

至此我们就完成了 leetcode-剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

如有任何问题或建议,欢迎留言讨论!