Loading

算法:二叉树公共父节点

题目

https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/

题目

思路1

采用从上到下找当节点是不是p的父节点,然后反向遍历p的父节点,返回是不是q的父节点就行。

代码1

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        /** 解法1:找出p所有的父节点,然后找出q所有的父节点。反向遍历能找到公共的子节点 */
        if (isParent(p , q) ) {
            return p;
        }
        if (isParent(q, p)) {
            return q;
        }
        
        List<TreeNode> parents = new ArrayList<TreeNode>();
        addParent(root, p,parents);
        for(int i = parents.size() -1 ; i >=0 ;i --) {
            TreeNode current = parents.get(i);
            if (isParent(current, q)) {
                return current;
            }
        }
        for (int i = 0; i < parents.size();i ++) {
            System.out.println(parents.get(i).val);
        }
        return root;
    }

    private void addParent(TreeNode root, TreeNode target, List<TreeNode> parents) {
        if (isParent(root, target)) {
            parents.add(root);
        }
        if (root == null) {
            return;
        }
        addParent(root.left, target, parents);
        addParent(root.right, target, parents);
    }

    private boolean isParent(TreeNode parent, TreeNode child) {
        if (parent == null) {
            return false;
        }
        if (parent == child) {
            return true;
        }
        return isParent(parent.left,child) || isParent(parent.right, child);
    }
}

思路2

如果有个节点是p,q的公共父节点节点,那么这个节点的子树一定包含分别包含p,q,或者说这个节点就是p,他左右子树里面包含q,或者这个节点是q他的子树包含p。

代码2

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode ans;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root, p, q);
        return ans;
    }
    private boolean dfs(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return false;
        }
        boolean lson = dfs(root.left, p, q); //是pq是否有个在左子树里面
        boolean rson = dfs(root.right, p, q); //pq是否有个在右子树里面
        if (lson && rson || (root.val == p.val || root.val == q.val) && (lson || rson)) {
            ans = root;
        }
        return lson || rson || (root.val == p.val || root.val == q.val); // 如果满足都在左或者都在右就是root是pq的公共子节点,不满足 lson || rson 要考虑一种特殊的情况,就是p是q的父节点。即p为Root

    }
}

题目: 二叉搜索树的公共父节点。

二叉搜索树的性质,中序遍历的结果是从大到小的,也就是左子树的节点值始终比根节点小,右子树的值始终是比根节点的大。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        }
        if (root.val < q.val && root.val < p.val) {
            return lowestCommonAncestor(root.right, p, q );
        } else if (root.val> q.val && root.val > p.val) {
            return lowestCommonAncestor(root.left, p, q );
        }
        return root;
    }
}
posted @ 2021-01-03 15:29  lijuny  阅读(1147)  评论(0编辑  收藏  举报