在笔试中遇到了二叉树最低公共祖先的问题,现在将这个问题彻底地总结一下。其实相关问题还不少,比如二叉树是BST还是普通二叉树,二叉树存在指向父结点的指针吗?
1.二叉搜索树的情况,这样的情景下处理比较简单一些,前序遍历该二叉树,如果当前结点的值比两个所求结点大,则最低公共祖先肯定存在于当前结点的左子树中,如果当前结点的值比两个所求结点小,则最低公共祖先肯定存在于当前结点的右子树中,否则,当前结点即为所求LC.
/**
* 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)
{
if (root.val < p.val && root.val < q.val)
return lowestCommonAncestor(root.right,p,q);
else if (root.val > p.val && root.val > q.val)
return lowestCommonAncestor(root.left,p,q);
else
return root;
}
return null;
}
}
2.如果为普通二叉树且没有指向父结点的指针呢?如果可以使用辅助内存,可以把搜索所求结点的遍历路径保存下来,比如,放在ArrayList中,第一个相同结点即为LCA.如果不能使用辅助内存,就要使用难一点的递归求解了我。下面是整个过程的代码,可以在eclipse中单步运行查看过程,会理解得稍微深刻一些。
package com.leetcode.BinaryTree;
import java.util.ArrayList;
import java.util.Stack;
import com.nowcoder.TreeImp;
/**
* Created by yanglei 2017-3-22
*/
public class MyBinaryTree {
//
private TreeNode root=null;
/*
*
*/
public MyBinaryTree(){
root=new TreeNode(1,"root(3)");
}
/**
*
*
*/
public void createBTree(){
TreeNode newNode5=new TreeNode(2,"5");
TreeNode newNode1=new TreeNode(3,"1");
TreeNode newNode6=new TreeNode(4,"6");
TreeNode newNode2=new TreeNode(5,"2");
TreeNode newNode0=new TreeNode(6,"0");
TreeNode newNode8=new TreeNode(7,"8");
TreeNode newNode7=new TreeNode(8,"7");
TreeNode newNode4=new TreeNode(9,"4");
root.left=newNode5;
root.right=newNode1;
root.left.left=newNode6;
root.left.right=newNode2;
root.right.right=newNode8;
root.right.left=newNode0;
root.left.right.left=newNode7;
root.left.right.right=newNode4;
}
public TreeNode getRoot(){
return root;
}
public int getHeight(TreeNode subTree){
return height(subTree);
}
private int height(TreeNode node) {
if(node==null)
return 0;
else {
int l=height(node.left);
int r=height(node.right);
return (l<r)?(r+1):(l+1);
}
}
public int getSize(TreeNode subTree){
return size(subTree);
}
private int size(TreeNode node) {
if(node==null)
return 0;
else{
return 1+size(node.left)
+size(node.right);
}
}
/**
*
* @param subTree
* @param node
* @return
*/
public TreeNode getParent(TreeNode subTree,TreeNode node){
if(subTree==null)
return null;
if(subTree.left==node || subTree.right==node)
return subTree;
TreeNode p;
if((p=getParent(subTree.left,node))!=null)
return p;
else
return getParent(subTree.right,node);
}
public void preOrder(TreeNode subTree){
if(subTree==null)
return;
else{
visit(subTree);
preOrder(subTree.left);
preOrder(subTree.right);
}
}
public void inOrder(TreeNode subTree){
if(subTree==null)
return;
else{
inOrder(subTree.left);
visit(subTree);
inOrder(subTree.right);
}
}
public void postOrder(TreeNode subTree){
if(subTree==null)
return;
else{
postOrder(subTree.left);
postOrder(subTree.right);
visit(subTree);
}
}
public void nonRecPreOrder(TreeNode subTree){
Stack<TreeNode> stack=new Stack<>();
TreeNode p=subTree;
while(p!=null||stack.size()>0){
while(p!=null){
visit(p);
stack.push(p);
p=p.left;
}
if(stack.size()>0){
p=stack.pop();
p=p.right;
}
}
}
public void nonRecInOrder(TreeNode subTree){
Stack<TreeNode> stack=new Stack<>();
TreeNode p=subTree;
while(p!=null || stack.size()>0){
while(p!=null){
stack.push(p);
p=p.left;
}
if(stack.size()>0){
p=stack.pop();
visit(p);
p=p.right;
}
}
}
public void nonRecPostOrder(TreeNode subTree){
Stack<TreeNode> stack=new Stack<>();
TreeNode p=subTree;
TreeNode node=null;
while(p!=null){
for(;p.left!=null;p=p.left)
stack.push(p);
while(p!=null&&p.right==null||p.right==node){
visit(p);
//
node=p;
if(stack.size()==0)
return;
//
p=stack.pop();
}
stack.push(p);
p=p.right;
}
}
/**
*
* @param node
*/
private void visit(TreeNode node){
node.isVisited=true;
System.out.println("NodeValue: "+node.data+",key="+node.key);
}
/**
*
*/
private class TreeNode {
public boolean isVisited=false;
private String data="";
public TreeNode left=null;
public TreeNode right=null;
private int key=0;
private boolean rVisited=false;
public TreeNode(int key,String data){
this.key=key;
this.data=data;
}
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == null || q == null)
return null;
ArrayList<TreeNode> p_Path = new ArrayList<TreeNode>();
ArrayList<TreeNode> q_Path = new ArrayList<TreeNode>();
getPath(root,p,p_Path);
getPath(root,q,q_Path);
for (int i = 0;i < p_Path.size() && i < q_Path.size();i++)
{
if (p_Path.get(i).data == q_Path.get(i).data)
return p_Path.get(i);
}
return null;
}
public Boolean getPath(TreeNode root2, TreeNode p, ArrayList<TreeNode> p_Path) {
if (root2 == null || p == null)
return null;
if (root2 == p)
return true;
if (root2.left != null)
{
p_Path.add(root2.left);
if (getPath(root2.left,p,p_Path))
return true;
p_Path.remove(p_Path.size() - 1);
}
if (root2.right != null)
{
p_Path.add(root2.right);
if (getPath(root2.right,p,p_Path))
return true;
p_Path.remove(p_Path.size() - 1);
}
return false;
}
/*
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&&right!=null) return root;
return left == null ? right : left;
}
*/
public static void main(String[] args)
{
MyBinaryTree mt = new MyBinaryTree();
TreeNode root1 = mt.root;
MyBinaryTree pq = new MyBinaryTree();
mt.createBTree();
// mt.preOrder(root1);
TreeNode pTest = root1.left.left;
TreeNode qTest = root1.left.right.left;
TreeNode resultNode = mt.lowestCommonAncestor(root1, pTest, qTest);
System.out.println(resultNode.data.toString());
}
}