项目地址:https://github.com/SpecialYang/Sword-Means-Offer
问题
输入两个树的节点,求他们的公共的最低祖先节点。
解析
其实此类题目,如果不考虑各种优化的情况下,采用最普通的深度优先搜索,从跟节点记录到指定的节点的路径。这样我们遍历2次树后,就可以得到2条路径,求这两条路径最后一个相同的节点就是他们最低的公共祖先节点。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kAV41owM-1643243773031)(https://ws4.sinaimg.cn/large/006tNbRwly1fxw92reymmj30i40fm74n.jpg)]
上图中,4和6的最低公共祖先就是2。
从跟节点到4的路径为:1 -> 2 -> 4
从跟节点到6的路径为:1 -> 2 -> 5 -> 6
这两条路径的最后一个公共节点就是2,所以4和6的最低公共祖先为2。
这是最普通的场景,其实题目也可以根据树的种类不同,相应的解法也随之改变。
思路一
当树为二叉搜索树时,求给定2个节点的最低祖先节点。
二叉搜索树的定义:左子树的节点值都比跟节点小,右子树的节点值都比跟节点大,左右子树也遵循此约束。
此情况最简单,我们只需从跟节点开始,拿给定的2个节点之比较:
- 若两个都比当前节点小,则说明最低祖先在左子树,则下一次遍历节点为当前节点的左孩子
- 若两个都比当前节点大,则说明最低祖先在右子树,则下一次遍历节点为当前节点的右孩子
- 若一个比当前节点大,另一个比当前节点小,则说明给定的两个节点分别位于当前节点左右子树,这是他们第一次分开,所以就是他们的最低祖先,结束。
/**
* 二叉搜索树的最近公共父节点查找
* @param root
* @param target1
* @param target2
* @return
*/
public TreeNode getLastCommonTreeNodeOfBinarySearchTree(TreeNode root, TreeNode target1, TreeNode target2) {
if (target1.val < root.val && target2.val < root.val) {
return getLastCommonTreeNodeOfBinarySearchTree(root.left, target1, target2);
} else if (target1.val > root.val && target2.val > root.val) {
return getLastCommonTreeNodeOfBinarySearchTree(root.right, target1, target2);
} else {
return root;
}
}
思路二
若不是二叉搜索树,就只是普通的二叉树,但是每个节点有指向父节点的指针,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6FBdBwk2-1643243773033)(https://ws2.sinaimg.cn/large/006tNbRwly1fxw9hx3fg1j30f40f2t96.jpg)]
有了指向父节点的指针就好办了,因为我们可以从给定的节点逆向分别求出这两个节点到根节点的路径。
- 从4到根节点1的路径为:4 -> 2 -> 1
- 从6到根节点1的路径为:6 -> 5 -> 2 -> 1
这时我们只需求出这两个路径第一个公共节点即可,那么问题就转化为两个相交的单链表求交点问题了。详情见:剑指Offer-38-两个链表的第一个公共节点.