给定具有以下属性的二叉树,其所有叶子节点都处于正(+)符号,然后符号交替到达该路径的根。因此,根据路径,节点可以有多个符号。
现在我们需要找出每条路径的总和以及树的总和。
for ex:
there are 5 paths in the given binary tree.
path 1: 10-2+3-4 = 7
path 2: 19-8+2-3+4 = 14
path 3: 12-11+17-3+4 = 19
path 4: 2-9+1-4 = -10
path 5: 21-9+1-4 = 9
overall sum 39
这里的问题是决定每个节点的符号,该节点由它的底层路径中的叶节点控制。
我可以想到一个具有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);
}
无论如何都无法保存存储树所需的空间。请不要去制作树。假设您已获得树的根节点,并且已经构建了树。
我说的是运行特定算法来回答问题所需的额外空间。
答案 0 :(得分:0)
好吧,如果我们可以从底部到顶部遍历树,我们可以很容易地获得具有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 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;
}