Java 如何在线性时间和恒定空间中迭代查找二叉树(而不是二叉搜索树)中的最低公共祖先
我有下面的工作代码,可以在O(n)时间递归地找到二叉树(不是BST)的LCA,因为我使用递归,所以在O(n)空间中 但是,我需要在O(n)时间和O(1)空间中迭代执行此操作。 我有下面的代码,但它使用list保存两条路径,这两条路径使它成为O(n)时间和O(n)空间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>>();
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 p和depth\u q。让l在p和q中最低,并且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);
}
}