剑指Offer(第二版)面试案例:树中两个节点的最低公共祖先节点

来源:互联网 发布:js 读取数字证书 编辑:程序博客网 时间:2024/05/08 13:18


(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/74612786冷血之心的博客)


剑指Offer(第二版)面试案例:树中两个节点的最低公共祖先节点


题目:输入两个树节点,求它们的最低公共祖先节点。


反问:这棵树是不是二叉树?


面试官:是二叉树,并且是二叉搜索树。


思路:

二叉搜索树是经过排序的,位于左子树的节点都比父节点小,位于右子树的节点都比父节点大。既然要找最低的公共祖先节点,我们可以从根节点开始进行比较。

若当前节点的值比两个节点的值都大,那么最低的祖先节点一定在当前节点的左子树中,则遍历当前节点的左子节点;

反之,若当前节点的值比两个节点的值都小,那么最低的祖先节点一定在当前节点的右子树中,则遍历当前节点的右子节点;

这样,直到找到一个节点,位于两个节点值的中间,则找到了最低的公共祖先节点。


/** * Definition for a binary tree node. * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */public class Solution {    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {        if(root==null||root==p||root==q)            return root;        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);        else            return root;    }}


面试官:如果只是普通的二叉树呢?


反问:树的节点中有没有指向父节点的指针?


面试官:为什么需要指向父节点的指针?


答:如果存在parent指针,则分别从输入的p节点和q节点指向root根节点,其实这就是两个单链表。问题转化为求两个单链表相交的第一个公共节点


详见:链表基础题大全(一)



面试官:那如果不存在parent指针呢?



递归的解法如下:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {        if(root==null||root==p||root==q)            return root;        TreeNode left = lowestCommonAncestor(root.left,p,q);        TreeNode right = lowestCommonAncestor(root.right,p,q);        if (left == null)             return right;        if (right == null)             return left;        return root;    }


迭代解法:

需要我们保存下由root根节点到p和q节点的路径,并且将路径存入list中,则问题转化为求两个list集合的最后一个共同元素。

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {          if(root==null || p==null || q==null)         return null;        List<TreeNode> pathp = new ArrayList<>();          List<TreeNode> pathq = new ArrayList<>();          pathp.add(root);          pathq.add(root);                    getPath(root, p, pathp);          getPath(root, q, pathq);                    TreeNode lca = null;          for(int i=0; i<pathp.size() && i<pathq.size(); i++) {              if(pathp.get(i) == pathq.get(i))             lca = pathp.get(i);              else             break;          }          return lca;      }            private boolean getPath(TreeNode root, TreeNode n, List<TreeNode> path) {          if(root==n)               return true;                  if(root.left!=null) {              path.add(root.left);              if(getPath(root.left, n, path))            return true;              path.remove(path.size()-1);          }                    if(root.right!=null) {              path.add(root.right);              if(getPath(root.right, n, path))             return true;              path.remove(path.size()-1);          }          return false;      }

该题是互联网面试中出现频率贼高的二叉树题目。必须掌握哦~



如果对你有帮助,记得点赞哦~欢迎大家关注我的博客,可以进群366533258一起交流学习哦~



本群给大家提供一个学习交流的平台,内设菜鸟Java管理员一枚、精通算法的金牌讲师一枚、Android管理员一枚、蓝牙BlueTooth管理员一枚、Web前端管理一枚以及C#管理一枚。欢迎大家进来交流技术。





阅读全文
1 1
原创粉丝点击