我尝试编写程序,使用预订序列构建二叉搜索树。我知道有很多解决方案:最小/最大算法,经典(或“明显的”递归)或甚至迭代而不是递归。
我试图实现经典递归:预先遍历遍历的第一个元素是根。然后我搜索所有小于根的元素。所有这些元素都将成为左子树的一部分,其他值将成为右子树的一部分。我重复一遍,直到我构建所有的子句。这是一种非常经典的方法。
这是我的代码:
public static TreeNode constructInOrderTree(int[] inorder) {
return constructInOrderTree(inorder, 0, inorder.length-1);
}
private static TreeNode constructInOrderTree(int[] inorder, int start, int end){
if(start>end){
return null;
}
int rootValue = inorder[start];
TreeNode root = new TreeNode(rootValue);
int k = 0;
for (int i =0; i< inorder.length; i++){
if (inorder[i]<= rootValue){
k=i;
}
}
root.left = constructInOrderTree(inorder, start+1, k);
root.right= constructInOrderTree(inorder, k+1, end);
return root;
}
我的问题是:此算法的时间复杂度是多少?是O(n ^ 2)还是O(n * log(n))?
我在stackoverflow中搜索了这里,但我发现了许多相互矛盾的答案。有时,有人说它是O(n ^ 2),有时O(n * log(n)),我真的很困惑。
我们可以在这里应用主定理吗?如果是,“也许”我们可以考虑每次我们将树分成两个子树(相等的部分),所以我们将得到关系:(O(n)是在数组中搜索的复杂性)
T(n)= 1/2 * T(n / 2)+ O(n)
这会给我们带来O(n*log(n))
的复杂性。但是,我认为这不是真的,我们不将树分成相等的部分,因为我们在数组中搜索,直到我们找到了足够的元素没有?
可以在这里应用主定理吗?
答案 0 :(得分:1)
<强> Forethoughts:强>
不,WC中既不是O(n^2)
也不是O(nlogn)
。由于树木的性质以及您不对每个元素执行任何复杂操作的事实。所有你做的就是输出它,而不是用一些比较算法对它进行排序。
然后WC将是O(n)
。
这就是当树被歪斜时,即根的子树中的一个是空的。然后你有一个简单的链表。然后输出它,您必须至少访问每个元素一次,给出O(n)
。
<强>证明:强>
让我们假设正确的子树是空的,每次调用的努力是不变的(只打印出来)。然后
T(n) = T(n-1) + T(0) + c
T(n) = T(n-2) + 2T(0) + 2c
.
.
T(n) = nT(0) + nc = n(T(0) + c)
由于T(0)
和c
是常量,因此您最终会加入O(n)
。