如果两棵树包含相同的元素集但可能具有不同的结构,则称它们是相同的。 例如4,3,5和5,4,3
如何检查两棵树是否相同?
我能想到的一种方法是使用散列。对于第一个树中的每个元素,相应的计数递增。对于第二个树中的每个元素,计数递减。最后,哈希是空的,我们确信树是相同的。 时间复杂度:O(N) 空间复杂度:O(N)
但是,这种方法没有利用树是BST还是简单的BINARY TREE。
方法2:对数组中的两个树进行遍历遍历。我们有两个具有排序数据的数组。进行线性搜索以检查阵列是否相同。 时间复杂度:O(N) 空间复杂度:O(N)
但是,我想知道是否有更好的解决方案?
答案 0 :(得分:6)
这回答了最初措辞的问题,即在相同结构和元素意义上的树的身份之后。
比较有序(或任何其他)顺序化将不起作用:不同的树具有相同的遍历。例如,树木
[source]
具有相同的有序遍历a,b,c,d,e
。您可以使用two (different) traversals并分别检查它们是否相同。
然而,经典的解决方案是递归算法:
equal Leaf(x) Leaf(y) => x == y
| equal Node(x,l1,r1) Node(y,l2,r2) => x == y && equal(l1,l2) && equal(r1,r2)
| equal _ _ => false;
它同时在两个树上执行树遍历,并且花费时间Θ(n),n是相应节点数的最大值。
关于更新的问题,检查顺序遍历以获得元素相等就足够了。请注意,根据定义,BST的有序遍历是存储元素的排序列表,因此这种方法是正确的。以递归形式,这是算法:
inorder Leaf(x) = [x]
| inorder Node(x,l,r) = (inorder l) ++ [x] ++ (inorder r);
equal [] [] = true
| equal x1::r1 x2::r2 = x1 == x2 && (equal r1 r2)
| equal _ _ = false;
sameElems t1 t2 = let
e1 = inorder t1
e2 = inorder t2
in
equal e1 e2
end;
如果列表连接可以在时间O(1)中完成,则其在时间Θ(n)和空间Θ(n)中运行;迭代解决方案肯定同样好,并且可能有更好的常量。
如果你想在o(n)时间检查,你甚至无法查看每个元素。通常,两个树都包含成对不同的元素,因此您无法利用任何范围,因此我每次通用元素相等性检查都需要时间Ω(n)(假设一个更快的算法并构造它失败的两个树)。
但是,空间可以比O(n)更好。如果你按顺序实现cleverly¹,你只需要额外的O(1)空间(指向当前元素的指针,一些管理计数器/标志)。
答案 1 :(得分:1)
散列问题是如果你有两个二叉搜索树{2, 1, 3}
和{0, 0, 6}
,它们可以有相同的总哈希码,你仍然有不同的元素。
顺序遍历方法可能是最有效的方法,我怀疑O(n)
是你能得到的最好的,因为你需要进行n
次平等比较。 / p>
答案 2 :(得分:1)
你的后一个解决方案似乎比你的前一个更好,因为后者的最坏情况时间是O(N),最好的情况(有序遍历中的第一个元素不同)将是Ω(1) ,对于前者,最佳情况时间仍然是Ω(N),因为你必须等到最后才能确定。
作为后者的优化,你不能只使用指向每棵树中当前元素的指针而不是复制所有数据吗?用于有序遍历树的算法(至少具有自然排序)不需要制作数据的任何副本。这样你的空间复杂度就是O(1)。