यहाँ संदर्भ के लिए c # (.net) (ऊपर चर्चा की गई दोनों) में दो दृष्टिकोण हैं:
द्विआधारी वृक्ष (O (N) में LCA खोजने का पुनरावर्ती संस्करण - जैसा कि प्रत्येक नोड पर देखा जाता है) (समाधान का मुख्य बिंदु LCA है (a) केवल बाइनरी ट्री में नोड है जहां दोनों तत्व उपप्रकार के दोनों ओर रहते हैं (बाएं और दायां) LCA है। (b) और यह भी मायने नहीं रखता कि कौन सा नोड दोनों तरफ मौजूद है - शुरू में मैंने उस जानकारी को रखने की कोशिश की, और जाहिर है कि पुनरावर्ती कार्य इतना भ्रामक हो गया। एक बार जब मुझे यह एहसास हुआ, तो यह बहुत ही सुंदर हो गया।
दोनों नोड्स (O (N)) की खोज करना, और रास्तों पर नज़र रखना (अतिरिक्त स्थान का उपयोग करता है - इसलिए, # 1 शायद यह भी श्रेष्ठ है कि अंतरिक्ष शायद नगण्य है यदि बाइनरी ट्री अच्छी तरह से संतुलित है तो अतिरिक्त मेमोरी की खपत बस में होगी हे (लॉग (एन))।
इसलिए कि रास्तों की तुलना की जाती है (स्पष्ट रूप से स्वीकृत उत्तर के समान है - लेकिन पाइंटर नोड मानकर पथों की गणना बाइनरी ट्री नोड में मौजूद नहीं है)
बस पूरा करने के लिए ( प्रश्न से संबंधित नहीं ), BST में LCA (O (लॉग (N)))
टेस्ट
पुनरावर्ती:
private BinaryTreeNode LeastCommonAncestorUsingRecursion(BinaryTreeNode treeNode,
int e1, int e2)
{
Debug.Assert(e1 != e2);
if(treeNode == null)
{
return null;
}
if((treeNode.Element == e1)
|| (treeNode.Element == e2))
{
//we don't care which element is present (e1 or e2), we just need to check
//if one of them is there
return treeNode;
}
var nLeft = this.LeastCommonAncestorUsingRecursion(treeNode.Left, e1, e2);
var nRight = this.LeastCommonAncestorUsingRecursion(treeNode.Right, e1, e2);
if(nLeft != null && nRight != null)
{
//note that this condition will be true only at least common ancestor
return treeNode;
}
else if(nLeft != null)
{
return nLeft;
}
else if(nRight != null)
{
return nRight;
}
return null;
}
जहां सार्वजनिक विधि का पालन करके निजी पुनरावर्ती संस्करण को लागू किया जाता है:
public BinaryTreeNode LeastCommonAncestorUsingRecursion(int e1, int e2)
{
var n = this.FindNode(this._root, e1);
if(null == n)
{
throw new Exception("Element not found: " + e1);
}
if (e1 == e2)
{
return n;
}
n = this.FindNode(this._root, e2);
if (null == n)
{
throw new Exception("Element not found: " + e2);
}
var node = this.LeastCommonAncestorUsingRecursion(this._root, e1, e2);
if (null == node)
{
throw new Exception(string.Format("Least common ancenstor not found for the given elements: {0},{1}", e1, e2));
}
return node;
}
दोनों नोड्स के रास्तों पर नज़र रखते हुए समाधान:
public BinaryTreeNode LeastCommonAncestorUsingPaths(int e1, int e2)
{
var path1 = new List<BinaryTreeNode>();
var node1 = this.FindNodeAndPath(this._root, e1, path1);
if(node1 == null)
{
throw new Exception(string.Format("Element {0} is not found", e1));
}
if(e1 == e2)
{
return node1;
}
List<BinaryTreeNode> path2 = new List<BinaryTreeNode>();
var node2 = this.FindNodeAndPath(this._root, e2, path2);
if (node1 == null)
{
throw new Exception(string.Format("Element {0} is not found", e2));
}
BinaryTreeNode lca = null;
Debug.Assert(path1[0] == this._root);
Debug.Assert(path2[0] == this._root);
int i = 0;
while((i < path1.Count)
&& (i < path2.Count)
&& (path2[i] == path1[i]))
{
lca = path1[i];
i++;
}
Debug.Assert(null != lca);
return lca;
}
जहाँ FindNodeAndPath को परिभाषित किया गया है
private BinaryTreeNode FindNodeAndPath(BinaryTreeNode node, int e, List<BinaryTreeNode> path)
{
if(node == null)
{
return null;
}
if(node.Element == e)
{
path.Add(node);
return node;
}
var n = this.FindNodeAndPath(node.Left, e, path);
if(n == null)
{
n = this.FindNodeAndPath(node.Right, e, path);
}
if(n != null)
{
path.Insert(0, node);
return n;
}
return null;
}
BST (LCA) - संबंधित नहीं (केवल संदर्भ के लिए पूरा करने के लिए)
public BinaryTreeNode BstLeastCommonAncestor(int e1, int e2)
{
//ensure both elements are there in the bst
var n1 = this.BstFind(e1, throwIfNotFound: true);
if(e1 == e2)
{
return n1;
}
this.BstFind(e2, throwIfNotFound: true);
BinaryTreeNode leastCommonAcncestor = this._root;
var iterativeNode = this._root;
while(iterativeNode != null)
{
if((iterativeNode.Element > e1 ) && (iterativeNode.Element > e2))
{
iterativeNode = iterativeNode.Left;
}
else if((iterativeNode.Element < e1) && (iterativeNode.Element < e2))
{
iterativeNode = iterativeNode.Right;
}
else
{
//i.e; either iterative node is equal to e1 or e2 or in between e1 and e2
return iterativeNode;
}
}
//control will never come here
return leastCommonAcncestor;
}
यूनिट टेस्ट
[TestMethod]
public void LeastCommonAncestorTests()
{
int[] a = { 13, 2, 18, 1, 5, 17, 20, 3, 6, 16, 21, 4, 14, 15, 25, 22, 24 };
int[] b = { 13, 13, 13, 2, 13, 18, 13, 5, 13, 18, 13, 13, 14, 18, 25, 22};
BinarySearchTree bst = new BinarySearchTree();
foreach (int e in a)
{
bst.Add(e);
bst.Delete(e);
bst.Add(e);
}
for(int i = 0; i < b.Length; i++)
{
var n = bst.BstLeastCommonAncestor(a[i], a[i + 1]);
Assert.IsTrue(n.Element == b[i]);
var n1 = bst.LeastCommonAncestorUsingPaths(a[i], a[i + 1]);
Assert.IsTrue(n1.Element == b[i]);
Assert.IsTrue(n == n1);
var n2 = bst.LeastCommonAncestorUsingRecursion(a[i], a[i + 1]);
Assert.IsTrue(n2.Element == b[i]);
Assert.IsTrue(n2 == n1);
Assert.IsTrue(n2 == n);
}
}