我在网上法官遇到如下问题:
检查两个给定的二叉树是否相同。假设允许任意数量的调整。调整被定义为树中一个节点的子节点的交换。
我提出了以下接受的天真算法。
/**
* @aaram a, b, the root of binary trees.
* @return true if they are tweaked identical, or false.
*/
bool isTweakedIdentical(TreeNode* a, TreeNode* b) {
if (!a || !b)
return !a && !b;
return a->val == b->val &&
((isTweakedIdentical(a->left, b->left) && isTweakedIdentical(a->right, b->right)) ||
(isTweakedIdentical(a->left, b->right) && isTweakedIdentical(a->right, b->left)));
}
但是,我无法弄清楚我的解决方案的时间复杂性。任何人都可以教我如何分析它?我不确定最坏的情况何时发生。
答案 0 :(得分:0)
这取决于你期望树的“二进制”。
如果构建的树往往更加线性链接,那么您的算法将倾向于线性执行O(N)
(具有N个非尾调用递归,这可能导致堆栈溢出大树)。 / p>
如果您构建的树往往更加二进制,因为两个子节点的每个节点的树大小大致相等,那么您的算法将以对数方式执行对数, O(log2(N))
< / s> O(N^2)
。
最糟糕的情况是a
在右侧是线性的,而b
在左侧是线性的。您可以通过伪随机选择要检查的路径来改善您的平均情况,但是以每次调用函数调用rand()
为代价。我不知道这是否值得花费,但这只是一个建议。
修改强>
考虑二叉树的这个例子:
_1_
/ \
_2 3_
/ | | \
4 5 6 7
/| |\ /| |\
8 9 A B C D E F
_1_
/ \
_3 2_
/ | | \
7 6 5 4
/| |\ /| |\
F E D C B A 9 8
这是heaps
的两个例子。他们匹配,除了他们被镜像。这将需要对isTweakedIdentical()
进行43次调用才能返回true
。但这似乎是一个O(N)
操作,考虑到每个节点平均3次调用(根除了)。我稍后会完成编辑。
答案 1 :(得分:0)
对于初学者来说,让我们假设你正在使用一个包含n个节点的完美二叉树。在每个级别,您最多触发四个递归调用,每个调用都到一个二进制树,其中包含(大致)n / 2个节点。你每次调用都在做O(1)工作,所以我们得到了递归关系
T(n)≤4T(n / 2)+ O(1)
使用主定理,我们处于a = 4,b = 2和d = 0的情况下,并且因为log b a = log 2 4 = 2且d = 0,在这种情况下,我们看到运行时为O(n 2 )。
这个上限的问题在于它并不紧张。特别是,查看所进行的递归调用的结构,如果不存在短路,我们只能获得四次递归调用。这将要求在两种情况中的每一种情况下的第一次调用返回true,而第二次分支返回false。我花了最后半个小时试图制作一个最坏情况的树,并证明它是一个最坏情况的树,但我有一点时间这样做。我怀疑答案介于O(n log 2 3 )之间,这是每个节点三次调用得到的结果,O(n 2 < / sup>),但我不确定。遗憾!