leetcode面试准备:Lowest Common Ancestor of a Binary Search Tree & Binary Tree

1 题目

Binary Search Tree的LCA

Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______6______
/ \
___2__ ___8__
/ \ / \
0 _4 7 9
/ \
3 5

For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

接口: TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)

Binary Tree的LCA

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______3______
/ \
___5__ ___1__
/ \ / \
6 _2 0 8
/ \
7 4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

接口: TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)

2 思路

在二叉树数中寻找两个节点的最低公共父节点。更容易一点的题目是限定在搜索二叉树中。

搜索二叉树:左子树 < root < 右子树,即中序遍历有序。

思路1

遍历2次,找到节点pq的路径,然后在遍历1次两条路径,找到公共的最低节点。这个节点是所求的。

  • 搜索二叉树:利用BST性质,判断节点值的大小,很容易找到节点的路径。
  • 一般二叉树:DFS找公共节点

复杂度: 遍历3次,用了额外的储存空间。如何分析树的时间和空间复杂度?

思路2

树的结构,很容易想到递归。LCA要么在root上,要么在左右子树中。

  • 搜索二叉树

    根据BST的性质,两个节点p,q的公共袓先root, 一定满足p <= root <= q 或者 p >= root >= q。

    使用递归可以轻松解决此问题。分为三种情况讨论:
  1. P, Q都比root小,则LCA在左树,我们继续在左树中寻找LCA
  2. P, Q都比root大,则LCA在右树,我们继续在右树中寻找LCA
  3. 其它情况,表示P,Q在root两边,或者二者其一是root,或者都是root,这些情况表示root就是LCA,直接返回root即可。
  • 一般二叉树

    The idea is to traverse the tree starting from root. 具体见代码实现吧。
  1. If any of the given keys (n1 and n2) matches with root, then root is LCA (assuming that both keys are present).
  2. If root doesn’t match with any of the keys, we recur for left and right subtree. The node which has one key present in its left subtree and the other key present in right subtree is the LCA.
  3. If both keys lie in left subtree, then left subtree has LCA also, otherwise LCA lies in right subtree.

3 代码

BST的LCA

只写了思路2的代码

	// 递归
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null)
return root;
final int value = root.val;
if (Math.max(p.val, q.val) < value)
return lowestCommonAncestor(root.left, p, q);
if (Math.min(p.val, q.val) > value)
return lowestCommonAncestor(root.right, p, q);
return root;
} // 迭代做法
public TreeNode lca(TreeNode root, TreeNode p, TreeNode q) {
TreeNode cur = root;
for (;;) {
int value = cur.val;
if (p.val < value && q.val < value)
cur = cur.left;
else if (p.val > value && q.val > value)
cur = cur.right;
else
return cur;
}
}

BT的LCA

思路2的代码

	public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
} // If the root is one of a or b, then it is the LCA
if (root == p || root == q) {
return root;
} TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q); // If both nodes lie in left or right then their LCA is in left or right,
// Otherwise root is their LCA
if (left != null && right != null) {
return root;
} return (left != null) ? left : right;
}

思路1的代码

	public TreeNode lca(TreeNode root, TreeNode p, TreeNode q) {
Deque<TreeNode> pPath = new LinkedList<TreeNode>();
Deque<TreeNode> qPath = new LinkedList<TreeNode>();
findPath(root, p, pPath);
findPath(root, q, qPath); TreeNode prev = null;
for (; !pPath.isEmpty() && !qPath.isEmpty();) {
TreeNode parent = pPath.removeFirst();
if (parent == qPath.removeFirst()) {
prev = parent;
} else {
break;
}
}
return prev;
} /**
* DFS 寻找路径
*/
private boolean findPath(TreeNode root, TreeNode node, Deque<TreeNode> path) {
if (root == null)
return false;
if (root == node) {
path.addLast(root);
return true;
}
path.addLast(root);
if (findPath(root.left, node, path))
return true;
if (findPath(root.right, node, path))
return true;
path.removeLast();
return false;
}

4 总结

树的题目,不熟悉,多总结一下吧。

5 参考

leetcode面试准备:Lowest Common Ancestor of a Binary Search Tree & Binary Tree的更多相关文章

  1. 【LeetCode】236. Lowest Common Ancestor of a Binary Tree 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  2. Leetcode之236. Lowest Common Ancestor of a Binary Tree Medium

    236. Lowest Common Ancestor of a Binary Tree Medium https://leetcode.com/problems/lowest-common-ance ...

  3. 【一天一道LeetCode】#235. Lowest Common Ancestor of a Binary Search Tree

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  4. 【LeetCode】235. Lowest Common Ancestor of a Binary Search Tree 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 [LeetCode] https://leet ...

  5. LeetCode 【235. Lowest Common Ancestor of a Binary Search Tree】

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

  6. 【LeetCode 236】Lowest Common Ancestor of a Binary Tree

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  7. 【LeetCode 235】Lowest Common Ancestor of a Binary Search Tree

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

  8. LeetCode OJ 236. Lowest Common Ancestor of a Binary Tree

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  9. LeetCode OJ 235. Lowest Common Ancestor of a Binary Search Tree

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

随机推荐

  1. 安卓百度地图开发so文件引用失败问题研究

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园: 追风917 # 问题 首先,下面的问题基本都是在Android Studio下使用不当导致,eclipse是百 ...

  2. 通过修改ajaxFileUpload.js实现多图片动态上传并实现预览

    参考:http://smotive.iteye.com/blog/1903606 大部分我也是根据他的方法修改的,我也要根据name实现动态的多文件上传功能,但是有个问题使我一直无法实现多文件上传. ...

  3. 那天有个小孩跟我说LINQ(五)转载

    2  LINQ TO SQL(代码下载)      我们以一个简单的销售的业务数据库为例子         表结构很简单:Users(购买者(用户)表),Products(产品信息表),Sales(销 ...

  4. C# 简单的图像边缘提取

    博主做的很简单,大家看一看就好了...... 用到的算法是robert算子,这是一种比较简单的算法: f(x,y)=sqrt((g(x,y)-g(x+1,y+1))^2+(g(x+1,y)-g(x,y ...

  5. 使用CLK.AspNet.Identity提供以角色为基础的访问控制(RBAC)

    使用CLK.AspNet.Identity提供以角色为基础的访问控制(RBAC) 程序代码下载 程序代码下载:点此下载 前言 ASP.NET Identity是微软所贡献的开源项目,用来提供ASP.N ...

  6. Java教程——CMD手动编译运行失败原因(高手略过)

    (仅对新手,高手略过)在学习Java初期,我们在利用cmd手动编译java程序的时候,会遇到编译成功,但运行却总是提示失败.已经排除了java配置环境的问题,Path和ClassPath以及%JAVA ...

  7. Qt 操作Excel

    Qt对Excel的数据读/写操作没有现存的类,需要使用QAxObject,下面是从网上下载下来的一个封装好的类,感觉还可以,一般情况下够用,拿来给大家分享. 头文件: #ifndef EXCELENG ...

  8. iframe框根据内容自适应高度

    1.页面 <iframe name="iframe_userCenter" id="iframe" frameborder=2 width=100% he ...

  9. LINUX开机启动过程

    LINUX开机启动过程 启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息 ...

  10. ssh命令:隧道代理+本地端口转发+远程端口转发

        0.前言 nc是一个在网络连接两端的好工具,同时也是也个临时的端口转发的好工具.(永久的端口转发用什么?用iptables) ssh也是这方面的好工具,好处是加密可靠可复用在一端操作即可,代价 ...