我写了下面的代码,用于在BST中找到一个三元组,最多可以增加0.但是很难确定时间复杂度。
find()方法的时间复杂度为O(logn)。时间复杂度是isTriplet()O(n ^ 2)?
bool find(Node* root, int target) {
if (root == NULL)
return false;
if (root->data == target)
return true;
return (target < root->data) ? find(root->left, target) : find(root->right, target);
}
bool isTriplet(Node* root, Node* actualRoot) {
if (root == NULL)
return false;
if (root->left == NULL && root->right == NULL)
return false;
int sum = root->data;
if (root->left)
sum += root->left->data;
else if (root->right)
sum += root->right->data;
sum = -1 * sum;
return (find(actualRoot, sum) || isTriplet(root->left, actualRoot) || isTriplet(root->right, actualRoot));
}
答案 0 :(得分:0)
sum = 0的三元组表示节点,左边和右边的子节点,三个元素的总和等于0。
让我们从逻辑上思考。我们应该从树根开始搜索这些三元组?基本上,如果根是正数,那么在左边,如果根是负数,那么在右边。
我们什么时候应该检查是否找到了这样的三联体?在三个数字中至少存在负数且至少为正数的情况下。 0是一个特例,我将单独处理。
如果找到这样的总和,那么我们应该返回它并且应该停止算法。因此,如果节点不是0并且没有三元组,那么我们知道要搜索哪个子树。如果它是三元组,那么我们有一个简单的情况,因为找到了解。如果当前节点为0,那么我们应检查其三元组是否为0.如果不是,则我们可以停止搜索,因为没有子树将包含正数和负数。例外,当然节点是当前节点为0且其子节点中的一个也是0.在这种情况下,我们也需要检查该子树。
对于最坏情况,该算法应具有基数2对数复杂度。证明:
当找到这样的三元组时,算法应该停止。
如果还没有找到这样的三元组且当前节点不是0,那么我们就会有一个有趣且无趣的子树。
如果还没有找到这样的三元组且当前节点为0,那么:
3.1。它的孩子都是0,我们已经找到了这样的三胞胎,
3.2。它的孩子都不是0,因此可以证明不存在这样的三元组,或
3.3。其中一个孩子是0而另一个孩子不是,在这种情况下,0孩子定义了有趣的子树,而另一个孩子则定义了无趣的子树。
由于所有情况都是由于解决方案的存在或不存在而轻易停止算法,或者将树减半为有趣且无趣的子树,因此算法在每个级别上遍历单个节点,因此其复杂性在最坏的情况下,等于树的高度,这是二元对数。