C++ 交替符号二叉树
给定一个具有以下属性的二叉树,该二叉树的所有叶节点都是正号(+),然后该路径的符号交替到根。因此,根据路径,节点可以有多个符号 现在我们需要求出每条路径的和以及树的和。 这里的问题是确定每个节点的符号,该符号由其底层路径中的叶节点控制 我可以想出一个时间复杂度为O(n)且空间为O(n)的解决方案,在这个解决方案中,我可以将每条路径保存为从根到底的向量遍历,然后从叶节点开始确定每个节点的符号,从而计算每条路径的和 现在谁能提出任何改进的方法,空间复杂度为O(1)。 首选任何递归或迭代方法 我希望我已经清楚地解释了这个问题。不过,如果有任何疑问,我会很快补充更多细节 编辑:二叉树是这样存储和实现的&不是在一个数组中C++ 交替符号二叉树,c++,algorithm,tree,C++,Algorithm,Tree,给定一个具有以下属性的二叉树,该二叉树的所有叶节点都是正号(+),然后该路径的符号交替到根。因此,根据路径,节点可以有多个符号 现在我们需要求出每条路径的和以及树的和。 这里的问题是确定每个节点的符号,该符号由其底层路径中的叶节点控制 我可以想出一个时间复杂度为O(n)且空间为O(n)的解决方案,在这个解决方案中,我可以将每条路径保存为从根到底的向量遍历,然后从叶节点开始确定每个节点的符号,从而计算每条路径的和 现在谁能提出任何改进的方法,空间复杂度为O(1)。 首选任何递归或迭代方法 我希望
struct node
{
int data;
struct node* left;
struct node* right;
};
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
int main()
{
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
}
在任何情况下都无法保存存储树所需的空间。请不要动手做这棵树。假设您获得了树的根节点,并且已经构建了树
我指的是运行特定算法来回答问题所需的额外空间。好的,因此,如果我们能够从下到上遍历树,我们可以轻松获得具有O(1)额外空间和O(n^2)时间复杂度的解:
for(every leaf in tree){
Node node = leaf;
int total = 0;
int sign = 1;
while(node != null){
total += sign*node.value;
node = node.parent;
sign *= -1;
}
print total;
}
对于时间复杂度为O(n)的自顶向下遍历,为了获得O(1)个额外空间,需要一个更复杂的算法
Node node = root;
Node last = null;
int total = 0;
int sign = 1;
boolean back = false;
while(node != null){
total += sign*node.value;
if(node is leaf){
if(sign == 1)
print total;//Need to check if sign is not positive
else
print -total;
back = true;//If this is leaf, we need to go back
total -= sign*node.value;
last = node;
node = node.parent;
}else if(back){
if(last is left child){
back = false;
node = node.rightChild;
}else{//We need to continue to go back if we are going back and this is right child
last = node;
total -= sign*node.value;
node = node.parent;
}
}else{
total += sign*node.value;
node = node.leftChild;
}
sign *= -1;
}
注意:
- 使用堆栈的递归自上而下遍历或迭代遍历很容易产生O(n)空间复杂性,所以要小心
- 如果每个节点中没有父链接,我们就无法解决这个问题,因为在这种情况下,需要一个类似堆栈的数据结构来遍历树
Node node = root;
Node last = null;
int total = 0;
int sign = 1;
boolean back = false;
while(node != null){
total += sign*node.value;
if(node is leaf){
if(sign == 1)
print total;//Need to check if sign is not positive
else
print -total;
back = true;//If this is leaf, we need to go back
total -= sign*node.value;
Node tmp = last;//For leaf node, we can just use variable last
last = node;
node = tmp;
}else if(back){
if(last is not right child){
back = false;
last = node;
node = node.rightChild;
}else{//We need to continue to go back if we are going back and this is right child
last = node;
total -= sign*node.value;
node = node.leftChild;
}
}else{
total += sign*node.value;
Node tmp = node.leftChild;
node.leftChild = last;
last = node;
node = tmp;
}
sign *= -1;
}
你需要最大化总和吗?无法理解决定非叶节点符号的标准。不,我们不需要最大化和。标准很简单:叶节点是正号&然后该路径的符号交替到根。因此,一个节点可以有多个符号,这取决于路径。你说的O(1)是什么意思,你至少要穿过节点一次。你能解释一下你打算如何在O(n)时间和空间中完成它吗?@sasha:我说的是O(1)空间而不是O(1)时间O(1)空间意味着不使用任何额外的空间。我将使用路径数组path[]来存储当前根到叶的路径。以自上而下的方式从根部移动到所有叶片。遍历时,将当前路径中所有节点的数据存储在数组路径[]中。当我们到达叶节点时,我们可以停止。
Node node = root;
Node last = null;
int total = 0;
int sign = 1;
boolean back = false;
while(node != null){
total += sign*node.value;
if(node is leaf){
if(sign == 1)
print total;//Need to check if sign is not positive
else
print -total;
back = true;//If this is leaf, we need to go back
total -= sign*node.value;
Node tmp = last;//For leaf node, we can just use variable last
last = node;
node = tmp;
}else if(back){
if(last is not right child){
back = false;
last = node;
node = node.rightChild;
}else{//We need to continue to go back if we are going back and this is right child
last = node;
total -= sign*node.value;
node = node.leftChild;
}
}else{
total += sign*node.value;
Node tmp = node.leftChild;
node.leftChild = last;
last = node;
node = tmp;
}
sign *= -1;
}