এখানে রেফারেন্সের জন্য সি # (। নেট) এ দুটি পন্থা (উপরে আলোচনা করা হয়েছে):
বাইনারি ট্রিতে এলসিএ সন্ধানের পুনরাবৃত্ত সংস্করণ (ও (এন) - বেশিরভাগ প্রতিটি নোডটি পরিদর্শন করা হয়) (সমাধানের মূল বিষয়গুলি হল এলসিএ হল (ক) বাইনারি গাছের কেবল নোড যেখানে উভয় উপাদান সাবট্রির উভয় পাশেই থাকে (বাম এবং ডান) এলসিএ। (খ) এবং কোন নোড উভয় পক্ষের উপস্থিত রয়েছে সে বিষয়টিও গুরুত্বপূর্ণ নয় - প্রারম্ভিকভাবে আমি সেই তথ্যটি রাখার চেষ্টা করেছি এবং স্পষ্টতই পুনরাবৃত্ত ফাংশনটি এত বিভ্রান্ত হয়ে পড়েছে once আমি যখন বুঝতে পেরেছিলাম এটি খুব মার্জিত হয়ে ওঠে।
উভয় নোড (ও (এন)) অনুসন্ধান করা, এবং পাথের ট্র্যাক রাখা (অতিরিক্ত স্থান ব্যবহার করে - সুতরাং, # 1 সম্ভবত বর্ধনের গাছটি সুষম হয় তবে অতিরিক্ত মেমরির খরচ ঠিক তেমন হবে বলে ভেবেও স্থান সম্ভবত নগণ্য বলে মনে হয় হে (লগ (এন))।
যাতে পাথগুলি তুলনা করা হয় (স্বীকৃত উত্তরের সাথে অবশ্যই অনুরূপ - তবে পাথরগুলি পয়েন্টার নোডটি বাইনারি ট্রি নোডে উপস্থিত না ধরে ধরে গণনা করা হয়)
কেবলমাত্র সমাপ্তির জন্য ( প্রশ্নের সাথে সম্পর্কিত নয় ), বিএসটিতে এলসিএ (ও (লগ (এন))
টেস্ট
পুনরাবৃত্তি:
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;
}
বিএসটি (এলসিএ) - সম্পর্কিত নয় (কেবল রেফারেন্সের জন্য সম্পূর্ণ হওয়ার জন্য)
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);
}
}