求公共祖先(1)

求公共祖先

package _8题;

import java.util.ArrayList;
import java.util.List;

public class _4_7LCA {
	 public int getLCA(int a, int b) {
		    TreeNode<Integer> root = of(10);

		    TreeNode<Integer> lca = getLCA2(root, new TreeNode<Integer>(a), new TreeNode<Integer>(b));
		    return lca == null ? -1 : lca.val;
		  }
               //求公共祖先 
		  private TreeNode<Integer> getLCA(TreeNode<Integer> root, TreeNode<Integer> p, TreeNode<Integer> q) {
		    if (root == null) return null;
		    if (root.equals(p) || root.equals(q)) return root;

		    boolean is_p_on_left = cover(root.left, p);//辅助方法
		    boolean is_q_on_right = cover(root.right, q);
		    if (is_p_on_left == is_q_on_right) {//在root的两端
		      return root;
		    } else if (is_p_on_left) {//在root的左端
		      return getLCA(root.left, p, q);
		    } else {
		      return getLCA(root.right, p, q); //在右端
		    }
		  }

		  private TreeNode<Integer> getLCA2(TreeNode<Integer> root, TreeNode<Integer> p, TreeNode<Integer> q) {
		    if (root == null) return null;
		    if (root.equals(p) && root.equals(q)) return root;

		    TreeNode<Integer> x = getLCA2(root.left, p, q);//x是lca,或者是p(p在这一侧),或者是q(q在这一侧),或者是null(pq都不在这一侧)
		    if (x != null && !x.equals(p) && !x.equals(q)) {//在左子树找到了lca
		      return x;
		    }

		    TreeNode<Integer> y = getLCA2(root.right, p, q);
		    if (y != null && !y.equals(p) && !y.equals(q)) {//在右子树找到了lca
		      return y;
		    }

		    //  x:p,q,null y :q,p,null
		    if (x != null && y != null) {//一边找着一个
		      return root;
		    } else if (root.equals(p) || root.equals(q)) {
		      return root;
		    } else {
		      return x == null ? y : x;//有一个不为null,则返回,都为null,返回null
		    }
		  }

		  /**
		   * 判断x节点是否在n所代表的子树中
		   * @param n
		   * @param x
		   * @return
		   */
		  private boolean cover(TreeNode<Integer> n, TreeNode<Integer> x) {
		    if (n == null) return false;
		    if (n.equals(x)) return true;
		    return cover(n.left, x) || cover(n.right, x);
		  }

		  public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
		    //发现目标节点则通过返回值标记该子树发现了某个目标结点
		    if (root == null || root.equals(p.val) || root.equals(q)) return root;
		    //查看左子树中是否有目标结点,没有为null
		    TreeNode left = lowestCommonAncestor(root.left, p, q);
		    //查看右子树是否有目标节点,没有为null
		    TreeNode right = lowestCommonAncestor(root.right, p, q);
		    //都不为空,说明做右子树都有目标结点,则公共祖先就是本身
		    if (left != null && right != null) return root;
		    //如果发现了目标节点,则继续向上标记为该目标节点
		    return left == null ? right : left;
		  }


		  static TreeNode<Integer> of(int n) {
		    List<TreeNode<Integer>> list = new ArrayList<TreeNode<Integer>>();
		    for (int i = 0; i < n; i++) {
		      list.add(new TreeNode<Integer>(i + 1));
		    }
		    for (int i = 0; i < n; i++) {
		      TreeNode<Integer> parent = list.get(i);
		      if (i * 2 + 1 < n) {
		        TreeNode<Integer> left = list.get(i * 2 + 1);
		        parent.left = left;
		        left.parent = parent;
		      } else break;
		      if (i * 2 + 2 < n) {
		        TreeNode<Integer> right = list.get(i * 2 + 2);
		        parent.right = right;
		        right.parent = parent;
		      }
		    }
		    return list.get(0);
		  }

		  private static class TreeNode<T> {
		    public T val;
		    public TreeNode<T> left = null;
		    public TreeNode<T> right = null;
		    TreeNode<T> parent;

		    public TreeNode(T val) {
		      this.val = val;
		    }

		    @Override
		    public boolean equals(Object o) {
		      if (this == o) return true;
		      if (o == null || getClass() != o.getClass()) return false;

		      TreeNode<?> treeNode = (TreeNode<?>) o;

		      return val != null ? val.equals(treeNode.val) : treeNode.val == null;
		    }

		    @Override
		    public int hashCode() {
		      return val != null ? val.hashCode() : 0;
		    }
		  }
public static void main(String[] args) {
	  _4_7LCA obj = new _4_7LCA();
	    int lca = obj.getLCA(1, 3);
         System.out.println(lca);
	    lca = obj.getLCA(4, 10);

	    lca = obj.getLCA(4, 5);

	    lca = obj.getLCA(4, 6);

}
}

在这里插入图片描述
1和3的公共祖先是1;
4和10的公共祖先是2;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金石不渝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值