Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在线性时间和恒定空间中迭代查找二叉树(而不是二叉搜索树)中的最低公共祖先_Java_Algorithm_Binary Tree - Fatal编程技术网

Java 如何在线性时间和恒定空间中迭代查找二叉树(而不是二叉搜索树)中的最低公共祖先

Java 如何在线性时间和恒定空间中迭代查找二叉树(而不是二叉搜索树)中的最低公共祖先,java,algorithm,binary-tree,Java,Algorithm,Binary Tree,我有下面的工作代码,可以在O(n)时间递归地找到二叉树(不是BST)的LCA,因为我使用递归,所以在O(n)空间中 但是,我需要在O(n)时间和O(1)空间中迭代执行此操作。 我有下面的代码,但它使用list保存两条路径,这两条路径使它成为O(n)时间和O(n)空间 public class LCA { List<List<TreeNode>> bothPaths = new ArrayList<List<TreeNode>>();

我有下面的工作代码,可以在O(n)时间递归地找到二叉树(不是BST)的LCA,因为我使用递归,所以在O(n)空间中

但是,我需要在O(n)时间和O(1)空间中迭代执行此操作。 我有下面的代码,但它使用list保存两条路径,这两条路径使它成为O(n)时间和O(n)空间

public class LCA {
    List<List<TreeNode>> bothPaths = new ArrayList<List<TreeNode>>();
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(p == root || q == root) return root;

        findPaths(root, new ArrayList<TreeNode>(), p);
        findPaths(root, new ArrayList<TreeNode>(), q);

        List<TreeNode> listP = bothPaths.get(0);
        List<TreeNode> listQ = bothPaths.get(1);
        int len = Math.min(listP.size(), listQ.size());

        TreeNode previous = null;

        for(int i=0; i<len; i++){
            if(listP.get(i) == listQ.get(i)){
                previous = listP.get(i);
            }
            else{
                break;
            }
        }
        return previous; // common element between 2 list
    }

    private void findPaths(TreeNode root, ArrayList<TreeNode> tempList, TreeNode temp){
        if(root == null) return;

        tempList.add(root);

        if(root == temp){
            bothPaths.add(tempList);
            return;
        }

        findPaths(root.left, new ArrayList<TreeNode>(tempList),temp);
        findPaths(root.right, new ArrayList<TreeNode>(tempList), temp);
    }
}
公共级生命周期评价{
列出两个路径=新建ArrayList();
公共TreeNode最低公共祖先(TreeNode根、TreeNode p、TreeNode q){
如果(p==root | | q==root)返回root;
findpath(root,newarraylist(),p);
FindPath(根,新ArrayList(),q);
List listP=bothpath.get(0);
List listQ=bothpath.get(1);
int len=Math.min(listP.size(),listQ.size());
TreeNode previous=null;

对于(int i=0;i假设你有父指针,从p和q向上到根,计算它们在树中的深度,比如m和n。然后,从p和q向上到根,一次一级,直到两次搜索的节点相同,但首先在树中向上| m-n |级,以p和q中离根较远的为准。

go up从p开始,除非你到达顶部。这将给你p节点的depth\u p。同样得到depth\u p。然后你将得到depth\u pdepth\u q。让lpq中最低,并且h较高是的。从l上升到|深度p-深度q|级别。此新节点与h一起将提供相同级别的两个节点。从这两个节点一起上升,它们将在公共父节点处相遇


PS:如果您没有父指针,那么您可以从左右两侧发送速度为1和1/2的迭代器。这些迭代器中的一个将到达某个公共节点中的另一个,您可以稍后将其用作根节点。

从p和q开始迭代,除非您到达顶部。将找到的所有节点记录到一个集合中。相交这些集合。谢谢@StepanYakovenko用于解决方案。但是,我需要一个使用常量空间的解决方案。此解决方案与我的类似。父指针不在那里,因此此解决方案不起作用。我知道您建议使用父指针的解决方案的变体(如果其在节点结构中)并做类似于找出两个链表的连接点的相同逻辑。
public class LCA {
    List<List<TreeNode>> bothPaths = new ArrayList<List<TreeNode>>();
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(p == root || q == root) return root;

        findPaths(root, new ArrayList<TreeNode>(), p);
        findPaths(root, new ArrayList<TreeNode>(), q);

        List<TreeNode> listP = bothPaths.get(0);
        List<TreeNode> listQ = bothPaths.get(1);
        int len = Math.min(listP.size(), listQ.size());

        TreeNode previous = null;

        for(int i=0; i<len; i++){
            if(listP.get(i) == listQ.get(i)){
                previous = listP.get(i);
            }
            else{
                break;
            }
        }
        return previous; // common element between 2 list
    }

    private void findPaths(TreeNode root, ArrayList<TreeNode> tempList, TreeNode temp){
        if(root == null) return;

        tempList.add(root);

        if(root == temp){
            bothPaths.add(tempList);
            return;
        }

        findPaths(root.left, new ArrayList<TreeNode>(tempList),temp);
        findPaths(root.right, new ArrayList<TreeNode>(tempList), temp);
    }
}