Lowest Common Ancestor of A Binary Tree

[分析]
最近公共祖先(LCA)是一个经典问题,以前没有好好研究过这个问题,不知道还有个Tarjan算法,今天开了眼界。一般有两种方法分别适用不同场景:
1)递归算法,适合在线单次查询,如本题;
2)Tarjan算法,适合批量查询,输入是一颗树和N对定点,为每个顶点(u,v)确定LCA。
有兴趣的同学看参考 https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.03.md, July讲得很全面清楚。
抛开算法本身做这道题目还有些学习点:
思路1:分别求出root到p和q的路径,求两条路径从根开始的最后一个公共节点。
实现中getPath2方法暴露没有对回溯掌握得还不够好,回溯时回溯到方法调用前的状态即可,不能多也不能少,这里就属于回溯过头了。
LinkedList被当做stack使用时get(0)获得的是栈顶元素,之前错误的认为调用get(i)就类似操作ArrayList的get(i), 按加入顺序返回。
思路2:经典的递归写法,牢记树的很多问题都可以用递归解决,因为树本身是递归描述的。


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;
        else return left != null ? left : right;
    }
    public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
        LinkedList<TreeNode> path1 = new LinkedList<TreeNode>();
        getPath(root, p, path1);
        LinkedList<TreeNode> path2 = new LinkedList<TreeNode>();
        getPath(root, q, path2);
        TreeNode lca = root;
        int i = path1.size() - 1, j = path2.size() - 1;
        while (i >= 0 && j >= 0) {
            if (path1.get(i) != path2.get(j))
                break;
            lca = path1.get(i);
            i--; j--;
        }
        return lca;
    }
	private boolean getPath(TreeNode root, TreeNode x, LinkedList<TreeNode> path) {
		if (root == null) return false;
		path.push(root);
		if (root == x || getPath(root.left, x, path) || getPath(root.right, x, path))
			return true;
		else{
			path.pop();
			return false;
		}
	}
	// Wrong version
    private boolean getPath2(TreeNode root, TreeNode x, LinkedList<TreeNode> path) {
        if (root == null)
            return false;
        path.push(root);
        if (root == x) {
            return true;
        }
        if (getPath(root.left, x, path))
            return true;
        else {
            if (!path.isEmpty()) {
                path.pop();
            }
            if (getPath(root.right, x, path))
                return true;
            else if (!path.isEmpty()) {
                path.pop();
            }
        }
        return false;
    }

你可能感兴趣的:(Lowest Common Ancestor of A Binary Tree)